"use strict";

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

var _postcss = _interopRequireDefault(require("postcss"));

var _ErrorHandler = require("../postcss-plugins/variableModificationPlugin/ErrorHandler");

var _fileHandling = require("./utils/fileHandling");

var _variableConvertorUtils = require("./variableConvertorUtils");

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

// import { RawSource } from 'webpack-sources';
const fs = require('fs');

let variablesRead = {};

const {
  errors,
  errTable,
  errHandler
} = require('../postcss-plugins/variableModificationPlugin/index');

const supportedProps = ['font-size', 'margin', 'margin-top', 'margin-bottom', 'margin-left', 'margin-right', 'padding', 'padding-top', 'padding-bottom', 'padding-left', 'padding-right', '^top', '^right', '^bottom', '^left', '^width', 'min-width', 'max-width', '^height', 'min-height', 'max-height', 'text-indent', 'clip', 'flex-basis', 'row-gap', 'gap', 'column-gap', 'flex']; // -- to convert the hyphen values to values --

/*
input : 
var(--zdt_uploadlist_default_width)
output : 
--zdt_uploadlist_default_width

comment : 
to make the variable object using the output as key and decl.prop such as font-size as value 
*/

function createFolderIfNonExistant(path) {
  if (!fs.existsSync(path)) {
    fs.mkdirSync(path, {
      recursive: true
    });
  }
}

function createFileIfNonExistant(path, content) {
  if (fs.existsSync(path)) {
    fs.writeFileSync(path, content, 'utf-8');
  }
}

class VariableConversionCollector {
  constructor(options = {}) {
    this.optimize = options.optimize;
    this.filename = options.cssVariableReplacementConfig;
    this.patterns = options.patterns; // console.log(options.patterns, this.patterns);

    this.initializeFiles();
  }

  initializeFiles() {
    createFolderIfNonExistant('./.cli/logs/');
    createFolderIfNonExistant('./.cli/config/variables/');
    createFolderIfNonExistant('./.cli/config/selectorWeight/');
    createFileIfNonExistant('./.cli/logs/unassignedVariables.log', '{}');
    createFileIfNonExistant('./.cli/logs/css_error.log', '{}');
  }

  apply(compiler) {
    const variables = {};
    const unassigned = {}; // console.log(windowsModification([this.filename])[0]);

    const rawdata = fs.readFileSync(this.filename);
    const data = JSON.parse(rawdata);
    const {
      settings: settingsObject,
      errorLog: errorLogStatus,
      errorInConsole: errorConsoleStatus,
      errorsAllowed,
      strictMode
    } = data; // If theres is no setting for default prop in settingsObject, set one.

    if (!settingsObject.default) {
      settingsObject.default = {
        allowed: ['px', 'em', 'fit-content', 'auto', '%', 'inherit', '-moz-fit-content', 'vh', '0', 'initial', 'vw'],
        replacements: {
          px: 'var(--zd_size$$)'
        },
        range: {
          start: -99999,
          end: 99999
        }
      };
    }
    /* 
    purpose of tap : to create a variable object such as:
    {
      --zdt_uploadlist_default_width : width,
      --zdt_uploadlist_default_height : height,
    }
    which will help in the conversion further
    */


    if (fs.existsSync('./.cli/config/variables/variableMapping.json')) {
      variablesRead = JSON.parse(fs.readFileSync('./.cli/config/variables/variableMapping.json', 'utf-8'));
      Object.keys(variablesRead.changes).forEach(key => {
        variables[key] = variablesRead.changes[key];
      });
    }

    compiler.hooks.compilation.tap('VariableConversionCollector', compilation => {
      compilation.hooks.optimizeModules.tap('VariableConversionCollector', modules => {
        const mods = modules.filter(x => x.type.includes('css'));
        mods.forEach(module => {
          const rootOriginal = _postcss.default.parse(module.content);

          const filename = module.issuer.resource;

          if (!filename.includes('node_modules')) {
            rootOriginal.walkRules(rule => {
              rule.walkDecls(decl => {
                decl.value.split(' ').forEach(val => {
                  if (val && val.includes('--') && !new RegExp(_variableConvertorUtils.ignoreVals.join('|'), 'gi').test(val) && decl.prop) {
                    const extractedValue = (0, _variableConvertorUtils.extractVariableName)(val);

                    if (!variables[extractedValue]) {
                      variables[extractedValue] = decl.prop;
                    } else {
                      if (new RegExp(supportedProps.join('|'), 'gi').test(decl.prop)) {
                        if (errorsAllowed.MULTIPLE_OCCURANCES) {
                          const errObj = {
                            decl,
                            type: 'MULTIPLE_OCCURANCES',
                            filename,
                            message: `${extractedValue} : ${variables[extractedValue]} already exists please check!`
                          };
                          errHandler.errorTable.push(errObj);
                          errHandler.errorFunction(errObj);
                        }
                      }
                    }
                  } else {
                    if (/^--/gi.test(decl.prop) && val.trim() !== '' && !variables[decl.prop]) {
                      if (!Object.keys(variablesRead.ignore).includes(decl.prop)) {
                        unassigned[decl.prop] = variables[decl.prop];
                      }
                    }
                  }
                });
              });
            });
            /*
             current value example: 
             {
                --zdt_uploadlist_default_width : --zd_upload_width,
                --zd_upload_width : width
             }
             expected value : 
             {
               --zdt_uploadlist_default_width : width,
               --zd_upload_width : width
             }
            
             conversion is done in the while loop below
            */

            Object.keys(variables).forEach(key => {
              while (variables[variables[key]]) {
                variables[key] = variables[variables[key]];
              }
            });
          }
        });
      }); // -- conversion for the root using variableConvertor --

      /* 
      input : 
      .a{
        padding : 20px 
      }
      output :
      // on settingObject file : 
      { padding : { replacements : { px : 'zd_size$$' }}} 
      .a{
        padding : zd_size20;
      }
      */

      compilation.hooks.optimizeModules.tap('VariableConversionCollector', modules => {
        const mods = modules.filter(x => x.type.includes('css'));
        mods.forEach(module => {
          const filename = module.issuer.resource;
          /*
            input : 
            filename : 'D:/MyWork/..../desk_client_app/supportapp/src/components/Avatar/Avatar.module.css,
          
             patterns.cssVariableReplacement: 
            // include src folder, include deskapp folder, exclude node modules
            "cssVariableReplacement": [
              "src",
              "deskapp",
              "!node_modules"
            ]
             
            output : 
            true or false
          */

          if (!(0, _fileHandling.isFileNameMatchingPluginPattern)({
            filename,
            filterArr: this.patterns.cssVariableReplacement
          })) {
            return;
          }

          const rootOriginal = _postcss.default.parse(module.content);

          module.content = (0, _variableConvertorUtils.variableConverter)(rootOriginal, variables, settingsObject).toString();
        });
      });
    });
    /*
      purpose of tap : to display the errors encountered so far 
      input : 
      all css files 
      output : 
      all errors that are present in the errTable arr
    */

    compiler.hooks.afterEmit.tap('error-display', () => {
      if (Object.keys(unassigned).length > 0 && strictMode) {
        console.log();
        console.log(unassigned);
        console.log();
        let str = '{\n';
        Object.keys(unassigned).forEach(key => {
          str += `"${key}" : "${unassigned[key]}",\n`;
        });
        str += '}';
        fs.writeFileSync('./.cli/logs/unassignedVariables.log', str, 'utf-8');
        throw new Error('^^^ Variables above have not been assigned! ^^^');
      }

      const avlTypes = new Set([]);
      const srtArr = errTable.sort((a, b) => {
        avlTypes.add(a.type);
        avlTypes.add(b.type);

        if (a.type < b.type) {
          return -1;
        }
      });

      if (errorConsoleStatus) {
        const errorHandler = new _ErrorHandler.ErrorHandler();
        avlTypes.forEach(type => {
          console.log('---------------------------------------------------------------------------------------------------------------------------');
          console.log(`Error Type : ${type}`);
          console.log('---------------------------------------------------------------------------------------------------------------------------');
          srtArr.forEach(err => {
            if (err.decl.prop && err.decl.value && err.type === type) {
              errorHandler.printError(err);
            }
          });
          console.log('---------------------------------------------------------------------------------------------------------------------------');
        });
      }

      if (errorLogStatus) {
        fs.writeFileSync('./.cli/logs/css_error.log', '');
        console.log('writing to logFile...');

        if (errors.length > 0) {
          errors.forEach((err, index) => {
            if (errTable[index].decl.prop && errTable[index].decl.value) {
              fs.appendFileSync('./.cli/logs/css_error.log', err);
            }
          });
        }
      }
    });
  }

}

var _default = VariableConversionCollector;
exports.default = _default;