"use strict";

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

var _path = _interopRequireDefault(require("path"));

var _fs = _interopRequireDefault(require("fs"));

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

var _jsonHelper = require("../utils/jsonHelper");

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

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

let resultFileName = `${process.cwd()}/result.json`;
let options = (0, _utils.getOptions)();
let {
  ssTest: {
    referBranch,
    currentBranch,
    serviceName,
    tokenGit,
    changesOnly
  }
} = options;
(0, _jsonHelper.jsonHelper)(resultFileName, 'tests.libraryImpactOnSource.compareBranch', referBranch);
(0, _jsonHelper.jsonHelper)(resultFileName, 'tests.libraryImpactOnSource.TestBranch', currentBranch);
(0, _jsonHelper.jsonHelper)(resultFileName, 'tests.libraryImpactOnSource.isExecuted', true);

let isValidModule = name => {
  if (name.includes('node_modules') && (name.includes(`@zohodesk${_path.default.sep}components`) || name.includes(`@zohodesk${_path.default.sep}dot`) || name.includes(`@zohodesk${_path.default.sep}icons`) || name.includes(`@zohodesk${_path.default.sep}svg`)) && !name.endsWith('docs.js')) {
    return true;
  }

  return !name.includes('index.js') && !name.endsWith('.css') && !name.endsWith('.png') && !name.includes('node_modules') && name.includes('src');
};

let getModuleName = modulePath => {
  let [name] = _path.default.parse(modulePath).name.split('.');

  if (modulePath.includes(`@zohodesk${_path.default.sep}components`)) {
    name = `@zohodesk/components/${name}`;
  } else if (modulePath.includes(`@zohodesk${_path.default.sep}dot`)) {
    name = `@zohodesk/dot/${name}`;
  }

  return name;
};

class LibraryImpactPlugin {
  constructor(options = {}) {
    this.options = options;
    this.options.filename = options.filename || 'js/moduleStats.js';
    this.topHtml = '<!DOCTYPE html><html><head><style>.sourcenameRow .methodDetail { clear: both; padding: 10px; position: relative;}.sourcenameRow.methodDetail > div{float: left; min-width: 50%; padding-bottom: 10px;}.noCoverage { color: red; width: 80%; padding: 10px;}.fl { float: left;}.fr { float: right ! important;}.pointer, #har tr[main] td { cursor: pointer;}.impactTestcaseRow { float: left; width: 45%; padding: 20px; margin-right: 5%; background: white; margin-bottom: 10px; box-sizing: border-box; border-bottom: 2px dotted #eee;}.anchorNone, .modifiedMethodRow:hover .anchorNone { text-decoration: none; color: #00bfff !important;}/* .impactTestcaseRow:hover { box-shadow: -3px 0px 10px #ddd, 2px 1px 3px #ddd;} */.impactedBy{ float: left; padding: 10px; margin-top: 11px; color: green; width: 80%;}div#impactTCListContainer { font-size: 15px;}.impactTestcaseRowContainer,.sourcenameRow{ display:flex; flex-direction:column;}summary{ outline:none;}details{ padding:25px 10px;}</style></head><body> <div class="sourcenameRow pointer bg-clr-hr">';
    this.bottomHtml = '</div> <script type="text/javascript"> const details = document.querySelectorAll("details"); details.forEach((targetDetail) => { targetDetail.addEventListener("click", () => { // Close all the details that are not targetDetail. details.forEach((detail) => { if (detail !== targetDetail) { detail.removeAttribute("open"); } }); }); }); </script></body></html>';
    this.resultJson = {};
  }

  apply(compiler) {
    let loggedInfo = false;
    compiler.hooks.beforeCompile.tap('LibraryImpactPlugin', () => {
      (0, _jsonHelper.jsonHelper)(resultFileName, 'tests.libraryImpactOnSource.startTime', Date.now());

      if (!loggedInfo) {
        (0, _utils.log)('\x1b[33m%s\x1b[0m', '************************************************************ \n ');
        (0, _utils.log)('\x1b[5m\x1b[44m%s\x1b[0m', 'Finding Impacted Source Files Please Wait ...');
        loggedInfo = true;
      }
    });
    compiler.hooks.emit.tap('LibraryImpactPlugin', compilation => {
      let stats = compilation.getStats().toJson();
      let results = {};
      let {
        modules
      } = stats;

      for (let module of modules) {
        let {
          name,
          reasons
        } = module;

        if (isValidModule(name)) {
          let references = new Set();
          let referencedby = new Set();
          let docsName;
          let fileName;
          compilation.modules.forEach(module => {
            module.reasons.forEach(reason => {
              let exportedValue = reason.dependency;

              if (exportedValue.type === 'harmony export imported specifier') {
                if (exportedValue.module.userRequest.includes(name.replace('.', ''))) {
                  docsName = exportedValue.name;
                }
              }
            });
          });
          let currentModuleName = name;

          if (Array.isArray(reasons)) {
            for (let reason of reasons) {
              let {
                moduleName
              } = reason;

              if (isValidModule(moduleName)) {
                let reasonedModuleName = moduleName;
                referencedby.add(reasonedModuleName);
              }
            }
          }

          for (let subModule of modules) {
            let {
              name: subModuleName,
              reasons
            } = subModule;

            if (isValidModule(subModuleName)) {
              let currentModuleName = subModuleName;

              if (Array.isArray(reasons)) {
                for (let reason of reasons) {
                  let {
                    moduleName: reasonedModuleName
                  } = reason;

                  if (name === reasonedModuleName) {
                    references.add(currentModuleName);
                  }
                }
              }
            }
          }

          results[currentModuleName] = {
            name: currentModuleName,
            references: Array.from(references),
            referencedby: Array.from(referencedby),
            docsName: docsName ? docsName : '',
            fileName: name ? name : currentModuleName
          };
        }
      }

      (0, _utils.getDependenciesImpactList)(currentBranch, referBranch, tokenGit, serviceName).then(impactedList => {
        this.resultJson = (0, _utils.getLibraryConflict)(JSON.stringify(results), impactedList, changesOnly);
        (0, _jsonHelper.jsonHelper)(resultFileName, 'tests.libraryImpactOnSource.result', this.resultJson);

        if (this.resultJson.result.status) {
          (0, _utils.log)(this.resultJson.response);
          this.resultJson.response.forEach(fileObject => {
            this.topHtml = this.topHtml + '<details><summary><b>Source Name: </b>' + fileObject.sourceName + '</summary><div class="impactTestcaseRowContainer"><div class="impactedBy"> ImpactedBy :- </div>';
            fileObject.impactedBy.forEach(fileName => {
              this.topHtml = this.topHtml + '<div class="impactTestcaseRow"><a class="anchorNone">' + fileName + '</a></div>';
            });
            this.topHtml = this.topHtml + '</div></details>';
          });
        } else {
          (0, _utils.log)('\n');
          (0, _utils.log)(this.resultJson.result.message);
          this.topHtml = this.topHtml + '<div style="font-size: xxx-large; text-align: center; padding-top: 50px;"> ' + this.resultJson.result.message + '</div>';
        }

        if (!_fs.default.existsSync('./coverageTest')) {
          _fs.default.mkdirSync('./coverageTest');

          _fs.default.writeFileSync('./coverageTest/impactLibrary.html', this.topHtml + this.bottomHtml, 'utf8');
        } else {
          _fs.default.writeFileSync('./coverageTest/impactLibrary.html', this.topHtml + this.bottomHtml, 'utf8');
        }

        (0, _jsonHelper.jsonHelper)(resultFileName, 'tests.libraryImpactOnSource.endTime', Date.now());
      });
    });
    compiler.hooks.done.tap('LibraryImpactPlugin', () => {
      (0, _utils.log)('\n');
      (0, _utils.log)('Compilation finished!!!');
    });
  }

}

exports.default = LibraryImpactPlugin;