"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.getConfigHash = getConfigHash;
exports.getConfigKeyContentHash = getConfigKeyContentHash;
exports.getConfigRequests = getConfigRequests;
exports.loadPluginConfig = loadPluginConfig;
exports.runConfigRequest = runConfigRequest;
function _utils() {
  const data = require("@parcel/utils");
  _utils = function () {
    return data;
  };
  return data;
}
var _serializer = require("../serializer.js");
function _logger() {
  const data = require("@parcel/logger");
  _logger = function () {
    return data;
  };
  return data;
}
var _PluginOptions = _interopRequireDefault(require("../public/PluginOptions"));
function _diagnostic() {
  const data = _interopRequireWildcard(require("@parcel/diagnostic"));
  _diagnostic = function () {
    return data;
  };
  return data;
}
var _Config = _interopRequireDefault(require("../public/Config"));
var _utils2 = require("../utils");
var _assetUtils = require("../assetUtils");
function _rust() {
  const data = require("@parcel/rust");
  _rust = function () {
    return data;
  };
  return data;
}
function _profiler() {
  const data = require("@parcel/profiler");
  _profiler = function () {
    return data;
  };
  return data;
}
var _RequestTracker = require("../RequestTracker");
var _projectPath = require("../projectPath");
var _buildCache = require("../buildCache");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
async function loadPluginConfig(loadedPlugin, config, options) {
  let loadConfig = loadedPlugin.plugin.loadConfig;
  if (!loadConfig) {
    return;
  }
  try {
    config.result = await loadConfig({
      config: new _Config.default(config, options),
      options: new _PluginOptions.default((0, _utils2.optionsProxy)(options, option => {
        config.invalidateOnOptionChange.add(option);
      })),
      logger: new (_logger().PluginLogger)({
        origin: loadedPlugin.name
      }),
      tracer: new (_profiler().PluginTracer)({
        origin: loadedPlugin.name,
        category: 'loadConfig'
      })
    });
  } catch (e) {
    throw new (_diagnostic().default)({
      diagnostic: (0, _diagnostic().errorToDiagnostic)(e, {
        origin: loadedPlugin.name
      })
    });
  }
}
const configKeyCache = (0, _buildCache.createBuildCache)();
async function getConfigKeyContentHash(filePath, configKey, options) {
  let cacheKey = `${(0, _projectPath.fromProjectPathRelative)(filePath)}:${configKey}`;
  let cachedValue = configKeyCache.get(cacheKey);
  if (cachedValue) {
    return cachedValue;
  }
  let conf = await (0, _utils().readConfig)(options.inputFS, (0, _projectPath.fromProjectPath)(options.projectRoot, filePath));
  if (conf == null || conf.config[configKey] == null) {
    // This can occur when a config key has been removed entirely during `respondToFSEvents`
    return '';
  }
  let contentHash = typeof conf.config[configKey] === 'object' ? (0, _utils().hashObject)(conf.config[configKey]) : (0, _rust().hashString)(JSON.stringify(conf.config[configKey]));
  configKeyCache.set(cacheKey, contentHash);
  return contentHash;
}
async function runConfigRequest(api, configRequest) {
  let {
    invalidateOnFileChange,
    invalidateOnConfigKeyChange,
    invalidateOnFileCreate,
    invalidateOnEnvChange,
    invalidateOnOptionChange,
    invalidateOnStartup,
    invalidateOnBuild
  } = configRequest;

  // If there are no invalidations, then no need to create a node.
  if (invalidateOnFileChange.size === 0 && invalidateOnConfigKeyChange.length === 0 && invalidateOnFileCreate.length === 0 && invalidateOnOptionChange.size === 0 && invalidateOnEnvChange.size === 0 && !invalidateOnStartup && !invalidateOnBuild) {
    return;
  }
  await api.runRequest({
    id: 'config_request:' + configRequest.id,
    type: _RequestTracker.requestTypes.config_request,
    run: async ({
      api,
      options
    }) => {
      for (let filePath of invalidateOnFileChange) {
        api.invalidateOnFileUpdate(filePath);
        api.invalidateOnFileDelete(filePath);
      }
      for (let {
        filePath,
        configKey
      } of invalidateOnConfigKeyChange) {
        let contentHash = await getConfigKeyContentHash(filePath, configKey, options);
        api.invalidateOnConfigKeyChange(filePath, configKey, contentHash);
      }
      for (let invalidation of invalidateOnFileCreate) {
        api.invalidateOnFileCreate(invalidation);
      }
      for (let env of invalidateOnEnvChange) {
        api.invalidateOnEnvChange(env);
      }
      for (let option of invalidateOnOptionChange) {
        api.invalidateOnOptionChange(option);
      }
      if (invalidateOnStartup) {
        api.invalidateOnStartup();
      }
      if (invalidateOnBuild) {
        api.invalidateOnBuild();
      }
    },
    input: null
  });
}
async function getConfigHash(config, pluginName, options) {
  if (config.result == null) {
    return '';
  }
  let hash = new (_rust().Hash)();
  hash.writeString(config.id);

  // If there is no result hash set by the transformer, default to hashing the included
  // files if any, otherwise try to hash the config result itself.
  if (config.cacheKey == null) {
    if (config.invalidateOnFileChange.size > 0) {
      hash.writeString(await (0, _assetUtils.getInvalidationHash)([...config.invalidateOnFileChange].map(filePath => ({
        type: 'file',
        filePath
      })), options));
    } else if (config.result != null) {
      try {
        hash.writeBuffer((0, _serializer.serializeRaw)(config.result));
      } catch (err) {
        throw new (_diagnostic().default)({
          diagnostic: {
            message: 'Config result is not hashable because it contains non-serializable objects. Please use config.setCacheKey to set the hash manually.',
            origin: pluginName
          }
        });
      }
    }
  } else {
    hash.writeString(config.cacheKey ?? '');
  }
  return hash.finish();
}
function getConfigRequests(configs) {
  return configs.filter(config => {
    // No need to send to the graph if there are no invalidations.
    return config.invalidateOnFileChange.size > 0 || config.invalidateOnConfigKeyChange.length > 0 || config.invalidateOnFileCreate.length > 0 || config.invalidateOnEnvChange.size > 0 || config.invalidateOnOptionChange.size > 0 || config.invalidateOnStartup || config.invalidateOnBuild;
  }).map(config => ({
    id: config.id,
    invalidateOnFileChange: config.invalidateOnFileChange,
    invalidateOnConfigKeyChange: config.invalidateOnConfigKeyChange,
    invalidateOnFileCreate: config.invalidateOnFileCreate,
    invalidateOnEnvChange: config.invalidateOnEnvChange,
    invalidateOnOptionChange: config.invalidateOnOptionChange,
    invalidateOnStartup: config.invalidateOnStartup,
    invalidateOnBuild: config.invalidateOnBuild
  }));
}