"use strict";

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

var _webpackSources = require("webpack-sources");

var _utils = require("./utils");

var _getI18nKeysFormModules = _interopRequireDefault(require("./utils/getI18nKeysFormModules"));

var _unicodeConversion = require("./utils/unicodeConversion");

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

/**
 * this plugin was creating the chunk specific i18n chunk's.
 */
// this plugin's kick  starter is apply method
const pluginName = 'I18nFilesEmitter';
const MODULE_TYPE = 'json/i18n';

const i18ntype = locale => `${MODULE_TYPE}/${locale}`;

class I18nFilesEmitter {
  constructor({
    allI18nObject,
    i18nManifestFileName,
    filenameTemplate,
    locales,
    jsonpFunc
  }) {
    this.locales = locales;
    this.allI18nObject = allI18nObject;
    this.filenameTemplate = filenameTemplate; // this.filenameTemplate =  "i18n-chunk/[locale]/[name].js"

    this.jsonpFunc = jsonpFunc;
    this.prevHashes = {};
    this.i18nManifestFileName = i18nManifestFileName;
  }

  emitAsset(compilation, filename, source, info) {
    // NOTE: info support  available since webpack v4.40.0 https://webpack.js.org/api/stats/#asset-objects
    if (!compilation.emitAsset) {
      compilation.assets[filename] = source;
    } else {
      compilation.emitAsset(filename, source, info);
    }
  } // this method for create object and assign value for i18nkeys


  getI18nObjectByLocale(i18nKeys, locale) {
    const data = {};
    i18nKeys.forEach(key => {
      data[key] = this.allI18nObject[locale][key];
    });
    return data;
  }

  getTemplateString(i18nKeys, locale) {
    const i18nObject = this.getI18nObjectByLocale(i18nKeys, locale);
    const convertedI18nObject = (0, _unicodeConversion.convertUnicode)(JSON.stringify(i18nObject, null, 0));
    return `${this.jsonpFunc}(${convertedI18nObject});`; // return `${this.jsonpFunc}(JSON.parse(${JSON.stringify(jsonToString(i18nObject))}));`;
  }

  renderI18nLocaleChunk(chunk, locale, i18nKeys) {
    // renderI18nLocaleChunk(chunk, locale, i18nKeys, compilation) {
    const filenameTemplate = this.filenameTemplate.replace(/\[locale\]/g, locale);
    const pathOptions = {
      chunk,
      contentHashType: i18ntype(locale)
    };
    return {
      render: () => new _webpackSources.RawSource(this.getTemplateString(i18nKeys, locale)),
      filenameTemplate,
      pathOptions,
      identifier: `${pluginName}.${chunk.id}.${locale}`,
      hash: chunk.contentHash[i18ntype(locale)]
    };
  }

  emitI18nFilesForChunk(chunk, compilation) {
    const i18nKeys = (0, _getI18nKeysFormModules.default)(chunk.modulesIterable);
    const manifestForChunk = {
      assets: {},
      hasI18n: false,
      hasChanges: false
    };

    if (!i18nKeys.length) {
      // why  it is not checked as 0
      return manifestForChunk;
    }

    manifestForChunk.hasI18n = true; // const locales  = ['en_US'];

    this.locales.forEach(locale => {
      const result = this.renderI18nLocaleChunk(chunk, locale, i18nKeys, compilation);
      const {
        filenameTemplate,
        pathOptions,
        render,
        identifier,
        hash
      } = result;
      const filePath = compilation.getPath(filenameTemplate, pathOptions);
      manifestForChunk.assets[locale] = filePath;

      if (this.prevHashes[identifier] === hash) {
        return;
      }

      manifestForChunk.hasChanges = true;
      this.prevHashes[identifier] = hash;
      this.emitAsset(compilation, filePath, render(), {
        locale,
        chunkId: chunk.id,
        chunkName: chunk.name
      }); // compilation.assets[filePath] = render();
    });
    return manifestForChunk;
  }

  emitI18nAssert(compilation) {
    let manifest = {};
    let needEmitManifest = false;
    compilation.chunks.forEach(chunk => {
      const manifestForChunk = this.emitI18nFilesForChunk(chunk, compilation);

      if (manifestForChunk.hasI18n) {
        manifest[chunk.id] = manifestForChunk.assets;
        needEmitManifest = needEmitManifest || manifestForChunk.hasChanges;
      }
    });

    if (needEmitManifest) {
      const manifestSource = new _webpackSources.RawSource(JSON.stringify(manifest));
      this.emitAsset(compilation, this.i18nManifestFileName, manifestSource, {
        desc: 'this file is has chunks-locales-assets mapping'
      });
    }
  }

  apply(compiler) {
    /*
      compiler.hooks.thisCompilation.tap(pluginName, compilation => {
        compilation.mainTemplate.hooks.renderManifest.tap(
          pluginName,
          (result, { chunk }) => {
            this.renderChunk(result, compilation, chunk);
          }
        );
           compilation.chunkTemplate.hooks.renderManifest.tap(
          pluginName,
          (result, { chunk }) => {
            this.renderChunk(result, compilation, chunk);
          }
        );
      });
      */
    // this below hook was tapped for create asssets(file) for chunk specific i18nChunk Files
    compiler.hooks.emit.tap(pluginName, compilation => {
      this.emitI18nAssert(compilation);
    });
  }
  /*
    renderChunk(result, compilation, chunk) {
      const i18nKeys = getI18nKeysFormModules(chunk.modulesIterable);
      // TODO: need to discuss with vimal ji can we chose this place for add i18n locale files ????
      // IDEA:  we chose this place for add i18n locale files ????
      if (i18nKeys.length > 0) {
        Object.keys(this.allI18nObject).forEach(locale => {
          result.push(
            this.renderI18nLocaleChunk(chunk, locale, i18nKeys, compilation)
          );
        });
      }
    }
    */


}

exports.default = I18nFilesEmitter;