text: "use strict";
  var __assign = (this && this.__assign) || function () {
      __assign = Object.assign || function(t) {
          for (var s, i = 1, n = arguments.length; i < n; i++) {
              s = arguments[i];
              for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                  t[p] = s[p];
          }
          return t;
      };
      return __assign.apply(this, arguments);
  };
  Object.defineProperty(exports, "__esModule", { value: true });
  var utils_1 = require("./utils");
  var _ = require("lodash");
  var common = require("../../../lib/common");
  var os = require("os");
  var path = require("path");
  var trace = require("../../../lib/trace");
  var ManifestBuilder = /** @class */ (function () {
      function ManifestBuilder(extRoot) {
          this.extRoot = extRoot;
          this.packageFiles = {};
          this.lcPartNames = {};
          this.data = {};
          this.deferredFiles = [];
          this.producesMetadata = false;
      }
      /**
       * Gets the path to the localized resource associated with this manifest
       */
      ManifestBuilder.prototype.getLocPath = function () {
          return this.getPath();
      };
      /**
       * Called just before the package is written to make any final adjustments.
       */
      ManifestBuilder.prototype.finalize = function (files, resourceData, builders) {
          var _this = this;
          this.deferredFiles.forEach(function (f) {
              _this.addFile(f, false);
              if (f.path && !files[f.path]) {
                  files[f.path] = f;
              }
              else if (!f.path) {
                  files[common.newGuid()] = f;
              }
          });
          return Promise.resolve(null);
      };
      /**
       * Gives the manifest the chance to transform the key that is used when generating the localization
       * strings file. Path will be a dot-separated set of keys to address the string (or another
       * object/array) in question. See vso-manifest-builder for an example.
       */
      ManifestBuilder.prototype.getLocKeyPath = function (path) {
          return path;
      };
      ManifestBuilder.prototype.prepResult = function (resources) {
          var resultData = resources ? this._getLocResult(resources, resources) : this.data;
          return utils_1.removeMetaKeys(resultData);
      };
      /**
       * Generate the manifest as a string.
       */
      ManifestBuilder.prototype.getResult = function (resources) {
          return JSON.stringify(this.prepResult(resources), null, 4).replace(/\n/g, os.EOL);
      };
      ManifestBuilder.prototype.getMetadataResult = function (resources) {
          return null;
      };
      /**
       * Gets the contents of the file that will serve as localization for this asset.
       * Default implementation returns JSON with all strings replaced given by the translations/defaults objects.
       */
      ManifestBuilder.prototype.getLocResult = function (translations, defaults) {
          return [
              {
                  partName: this.getPath(),
                  path: null,
                  content: JSON.stringify(this._getLocResult(this.expandResourceFile(translations), this.expandResourceFile(defaults)), null, 4).replace(/\n/g, os.EOL),
              },
          ];
      };
      ManifestBuilder.prototype._getLocResult = function (translations, defaults, locData, currentPath) {
          // deep iterate through this.data. If the value is a string that starts with
          // resource:, use the key to look in translations and defaults to find the real string.
          // Do the replacement
          var _this = this;
          if (locData === void 0) { locData = {}; }
          if (currentPath === void 0) { currentPath = []; }
          var currentData = currentPath.length > 0 ? _.get(this.data, currentPath) : this.data;
          Object.keys(currentData).forEach(function (key) {
              // Ignore localization comments
              if (key.startsWith("_") && key.endsWith(".comment")) {
                  return;
              }
              var val = currentData[key];
              if (typeof val === "string" &&
                  val.substr(0, ManifestBuilder.resourcePrefix.length) === ManifestBuilder.resourcePrefix) {
                  var locKey = val.substr(ManifestBuilder.resourcePrefix.length);
                  var localized = _.get(translations, locKey) || _.get(defaults, locKey);
                  if (localized) {
                      _.set(locData, currentPath.concat(key), localized);
                  }
                  else {
                      throw new Error("Could not find translation or default value for resource " + locKey);
                  }
              }
              else {
                  if (typeof val === "object" && val !== null) {
                      if (_.isArray(val)) {
                          _.set(locData, currentPath.concat(key), []);
                      }
                      else {
                          _.set(locData, currentPath.concat(key), {});
                      }
                      _this._getLocResult(translations, defaults, locData, currentPath.concat(key));
                  }
                  else {
                      _.set(locData, currentPath.concat(key), val);
                  }
              }
          });
          return locData;
      };
      /**
       * Resource files are flat key-value pairs where the key is the json "path" to the original element.
       * This routine expands the resource files back into their original schema
       */
      ManifestBuilder.prototype.expandResourceFile = function (resources) {
          var expanded = {};
          Object.keys(resources).forEach(function (path) {
              _.set(expanded, path, resources[path]);
          });
          return expanded;
      };
      /**
       * Get the raw JSON data. Please do not modify it.
       */
      ManifestBuilder.prototype.getData = function () {
          return this.data;
      };
      Object.defineProperty(ManifestBuilder.prototype, "files", {
          /**
           * Get a list of files to be included in the package
           */
          get: function () {
              return this.packageFiles;
          },
          enumerable: true,
          configurable: true
      });
      /**
       * Set 'value' to data[path] in this manifest if it has not been set, or if override is true.
       * If it has been set, issue a warning.
       */
      ManifestBuilder.prototype.singleValueProperty = function (path, value, manifestKey, override, duplicatesAreErrors) {
          if (override === void 0) { override = false; }
          if (duplicatesAreErrors === void 0) { duplicatesAreErrors = false; }
          var existingValue = _.get(this.data, path);
          if (!override && existingValue !== undefined) {
              if (duplicatesAreErrors) {
                  throw new Error(trace.format("Multiple values found for '%s'. Ensure only one occurrence of '%s' exists across all manifest files.", manifestKey, manifestKey));
              }
              else {
                  trace.warn("Multiple values found for '%s'. Ignoring future occurrences and using the value '%s'.", manifestKey, JSON.stringify(existingValue, null, 4));
              }
              return false;
          }
          else {
              _.set(this.data, path, value);
              return true;
          }
      };
      /**
       * Read a value as a delimited string or array and concat it to the existing list at data[path]
       */
      ManifestBuilder.prototype.handleDelimitedList = function (value, path, delimiter, uniq) {
          if (delimiter === void 0) { delimiter = ","; }
          if (uniq === void 0) { uniq = true; }
          if (_.isString(value)) {
              value = value.split(delimiter);
              _.remove(value, function (v) { return v === ""; });
          }
          var items = _.get(this.data, path, "").split(delimiter);
          _.remove(items, function (v) { return v === ""; });
          var val = items.concat(value);
          if (uniq) {
              val = _.uniq(val);
          }
          _.set(this.data, path, val.join(delimiter));
      };
      /**
       * Add a file to the vsix package
       */
      ManifestBuilder.prototype.addFile = function (file, defer) {
          if (defer === void 0) { defer = false; }
          if (defer) {
              this.deferredFiles.push(file);
              return file;
          }
          if (!file.partName && file.packagePath) {
              file.partName = file.packagePath;
          }
          if (_.isArray(file.partName)) {
              var lastAdd = null;
              for (var i = 0; i < file.partName.length; ++i) {
                  var newFile = __assign({}, file);
                  newFile.partName = file.partName[i];
                  lastAdd = this.addFile(newFile);
              }
              return lastAdd;
          }
          if (typeof file.assetType === "string") {
              file.assetType = [file.assetType];
          }
          file.path = utils_1.cleanAssetPath(file.path, this.extRoot);
          if (!file.partName) {
              file.partName = "/" + path.relative(this.extRoot, file.path);
          }
          if (!file.partName) {
              throw new Error("Every file must have a path specified name.");
          }
          file.partName = utils_1.forwardSlashesPath(file.partName);
          // Default the assetType to the partName.
          if (file.addressable && !file.assetType) {
              file.assetType = [utils_1.toZipItemName(file.partName)];
          }
          if (this.packageFiles[file.path]) {
              if (_.isArray(this.packageFiles[file.path].assetType) && file.assetType) {
                  file.assetType = this.packageFiles[file.path].assetType.concat(file.assetType);
                  this.packageFiles[file.path].assetType = file.assetType;
              }
          }
          // Files added recursively, i.e. from a directory, get lower
          // priority than those specified explicitly. Therefore, if
          // the file has already been added to the package list, don't
          // re-add (overwrite) with this file if it is an auto (from a dir)
          if (file.auto && this.packageFiles[file.path] && this.packageFiles[file.path].partName === file.partName) {
              // Don't add files discovered via directory if they've already
              // been added.
          }
          else {
              var existPartName = this.lcPartNames[file.partName.toLowerCase()];
              if (!existPartName || file.partName === existPartName) {
                  // key off a guid if there is no file path.
                  var key = file.path || common.newGuid();
                  if (this.packageFiles[key]) {
                      // Additional package paths is an UNSUPPORTED and UNDOCUMENTED feature.
                      // It may trample on other existing files with no warning or error.
                      // Use at your own risk.
                      var additionalPackagePaths = this.packageFiles[key]._additionalPackagePaths;
                      if (additionalPackagePaths) {
                          additionalPackagePaths.push(file.partName);
                      }
                      else {
                          this.packageFiles[key]._additionalPackagePaths = [file.partName];
                      }
                  }
                  else {
                      this.packageFiles[key] = file;
                      this.lcPartNames[file.partName.toLowerCase()] = file.partName;
                  }
              }
              else {
                  throw new Error("All files in the package must have a case-insensitive unique filename. Trying to add " +
                      file.partName +
                      ", but " +
                      existPartName +
                      " was already added to the package.");
              }
          }
          if (file.contentType && this.packageFiles[file.path]) {
              this.packageFiles[file.path].contentType = file.contentType;
          }
          return file;
      };
      ManifestBuilder.resourcePrefix = "resource:";
      return ManifestBuilder;
  }());
  exports.ManifestBuilder = ManifestBuilder;
  //# sourceMappingURL=manifest.js.map