"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.I18nRuntimeDealerPlugin = void 0;

var _webpack = require("webpack");

var _htmlWebpackPlugin = _interopRequireDefault(require("html-webpack-plugin"));

var _constants = require("./constants");

var _getI18nLoadingRuntimeModule = require("./getI18nLoadingRuntimeModule");

var _templateFileName = require("./templateFileName");

var _hashUtils = require("./utils/hashUtils");

var _urlConcat = require("../../../../server/urlConcat");

var _I18nFilesEmitPlugin = require("./I18nFilesEmitPlugin");

var _LocaleChunkAssetsStore = require("./LocaleChunkAssetsStore");

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

const {
  RawSource
} = _webpack.sources;
const pluginName = 'I18nRuntimeDealerPlugin'; // I18nExtractPlugin.loader = require.resolve('./loader');

class I18nRuntimeDealerPlugin {
  constructor(options) {
    this.options = options;
  }

  apply(compiler) {
    compiler.hooks.thisCompilation.tap(pluginName, compilation => {
      // Get store for cache
      this.store = (0, _LocaleChunkAssetsStore.getLocaleChunkAssetsStore)(compilation);

      if (!this.options.runtime) {
        return;
      }

      this.createI18nDownloadCodeInRuntimeFile(compilation);
      this.addI18nIntoInitialHtml(compilation);
    });
  }

  addI18nIntoInitialHtml(compilation) {
    const i18nStore = this.store;

    _htmlWebpackPlugin.default.getHooks(compilation).beforeAssetTagGeneration.tap(pluginName, hookOptions => {
      const {
        assets
      } = hookOptions;
      const {
        templateLabel,
        filename,
        publicPath = '',
        mainChunkName
      } = this.options; // const dummyContent = '// dummy comment';

      const dummyContentHash = 'qwertyuiopasdfghjkl';
      const entryPoint = compilation.entrypoints.get(mainChunkName);
      const initialChunks = Array.from(entryPoint.chunks).filter(c => c.canBeInitial() && c.id !== c.runtime);
      const initialI18nAssets = initialChunks.filter(c => i18nStore.isChunkHasI18n(c)).map(c => {
        const data = _I18nFilesEmitPlugin.I18nFilesEmitPlugin.createFilenameWithHash({
          compilation,
          fileNameTemplate: filename,
          chunk: c,
          locale: templateLabel,
          // NOTE: we used dummy  content hash.
          //  Because we have no plan on use in content hash to initial I18n chunks
          // So Dummy hash was being used it will not work  just skip warnings
          contentHash: dummyContentHash
        });

        return (0, _urlConcat.urlConcat)(publicPath, data.filename);
      });
      const allJSAssets = [...initialI18nAssets, ...assets.js].map(url => url.replaceAll('[locale]', templateLabel).replaceAll('%5Blocale%5D', templateLabel));
      return {
        assets: { ...assets,
          js: allJSAssets
        }
      };
    });
  }

  createI18nDownloadCodeInRuntimeFile(compilation) {
    const {
      chunkFilename,
      locales,
      localeVarName
    } = this.options;
    const chunkFilenameHasContentHash = (0, _hashUtils.hasContentHash)(chunkFilename);

    const getI18nChunks = mainChunk => this.filterI18nUsedChunks(mainChunk.getAllAsyncChunks());

    const I18nLoadingRuntimeModule = (0, _getI18nLoadingRuntimeModule.getI18nLoadingRuntimeModule)({
      getI18nChunks
    });
    const enabledChunks = new WeakSet();

    const chunkFilenameUrlGenerator = (i18nChunks, locale) => (0, _templateFileName.templateFileName)({
      compilation,
      localeVarName,
      dynamicFilename: chunkFilename,
      contentHashes: this.getContentHashes(locale),
      chunks: i18nChunks
    });

    const prefixFunc = () => _constants.I18N_CHUNK_NAME_GENERATION_SEGMENT;

    const handler = (entryRuntimeChunk, set) => {
      if (enabledChunks.has(entryRuntimeChunk)) {
        return;
      }

      enabledChunks.add(entryRuntimeChunk);
      const {
        chunkFilename,
        // filename: initialFilename,
        runtimeOptions
      } = this.options;

      if (typeof chunkFilename === 'string' && /\[(full)?hash(:\d+)?\]/.test(chunkFilename)) {
        set.add(_webpack.RuntimeGlobals.getFullHash);
      }

      set.add(_webpack.RuntimeGlobals.publicPath);
      compilation.addRuntimeModule(entryRuntimeChunk, new I18nLoadingRuntimeModule(set, {
        prefixFunc: chunkFilenameHasContentHash ? prefixFunc : chunkFilenameUrlGenerator,
        runtimeOptions,
        chunkFilename
      }));
    };

    compilation.hooks.runtimeRequirementInTree.for(_webpack.RuntimeGlobals.ensureChunkHandlers).tap(pluginName, handler);

    if (chunkFilenameHasContentHash) {
      compilation.hooks.processAssets.tap({
        name: pluginName,
        stage: _webpack.Compilation.PROCESS_ASSETS_STAGE_DERIVED // additionalAssets: true

      }, assets => {
        // eslint-disable-next-line no-underscore-dangle
        const entries = compilation._getChunkGraphEntries();

        function createRuntimeFilePerLocale({
          locale,
          runtimeFileName,
          runtimeFileSourceStr,
          i18nChunks
        }) {
          const newRuntimeName = runtimeFileName.replaceAll('[locale]', locale);
          const replaceText = chunkFilenameUrlGenerator(i18nChunks, locale);
          const replacedStr = runtimeFileSourceStr.replace(_constants.I18N_CHUNK_NAME_GENERATION_SEGMENT, replaceText);
          compilation.emitAsset(newRuntimeName, new RawSource(replacedStr));
        } // eslint-disable-next-line no-restricted-syntax


        for (const entryChunk of entries) {
          const i18nChunks = getI18nChunks(entryChunk);
          const runtimeFileName = [...entryChunk.files][0];
          const runtimeFileSourceStr = assets[runtimeFileName].source();
          locales.forEach(locale => createRuntimeFilePerLocale({
            locale,
            entryChunk,
            runtimeFileName,
            runtimeFileSourceStr,
            i18nChunks
          })); // NOTE: we don't delete, Because of HTML plugin needs to add runtime file in html
          // compilation.deleteAsset(runtimeFileName);
        }
      });
    }
  }

  filterI18nUsedChunks(chunks) {
    const i18nStore = this.store;
    return Array.from(chunks).filter(c => i18nStore.isChunkHasI18n(c.id));
  }

  getContentHashes(locale) {
    const i18nStore = this.store;
    const contentHashes = {};
    i18nStore.forEachChunkId(chunkId => {
      const contentHash = i18nStore.getContentHash(chunkId, locale);

      if (contentHash) {
        contentHashes[chunkId] = contentHash;
      }
    }); // console.log({ contentHashes });

    return contentHashes;
  }

}

exports.I18nRuntimeDealerPlugin = I18nRuntimeDealerPlugin;