"use strict";

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

const parser = require('@babel/parser');

const traverse = require('@babel/traverse').default;

const t = require("@babel/types");

const path = require('path');

function getFilename(originalFilePath) {
  const [fileName] = path.basename(originalFilePath).split('.');
  return fileName;
}

function convertKeyToValue(object = {}) {
  let keys = Object.keys(object);
  let values = Object.values(object);
  return keys.reduce((value, item, i) => {
    if (item.includes(',')) {
      item = item.replace(/{|}/g, "");
      item = '{ ' + item + ' }';
    }

    value = value + "'" + values[i] + "'" + ": " + item + ",";
    return value;
  }, '');
}

function mergeDuplicateValues(obj) {
  let mergedObj = {};

  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      let value = obj[key];
      let existingKey = Object.keys(mergedObj).find(k => mergedObj[k] === value);

      if (existingKey) {
        mergedObj[existingKey + ' , ' + key] = value;
        delete mergedObj[existingKey];
      } else {
        mergedObj[key] = value;
      }
    }
  }

  return mergedObj;
}

function enhancedReactLiveConverter(source, originalFilePath) {
  const fileName = getFilename(originalFilePath);

  if (!source) {
    return '';
  }

  let docCode = '';
  const fileContent = source.replace(/[\s\r\n]*$/, '');
  const ast = parser.parse(fileContent, {
    sourceType: 'module',
    plugins: ['jsx', 'classProperties']
  });

  function createImportStatements(input) {
    let output = '';

    for (const key in input) {
      if (input.hasOwnProperty(key) && key !== 'React') {
        output += `import ${key} from '${input[key]}';\n`;
      }
    }

    return output;
  }

  const importBlock = {};
  const printableCode = {};
  let remainingBlock = ''; // Traverse the AST and find the import and export blocks

  let remainingCode = ast.program.body.filter(node => node.type !== 'ImportDeclaration').filter(node => node.type !== 'ExpressionStatement').map(node => fileContent.substring(node.start, node.end)).join('').trim();
  traverse(ast, {
    ImportDeclaration(path) {
      path.node.specifiers.map(specifier => {
        if (t.isImportSpecifier(specifier)) {
          importBlock[`{ ${specifier.local.name} }`] = path.node.source.value;
          printableCode[`{ ${specifier.local.name} }`] = path.node.source.value;
          return `{'${specifier.imported.name}': ${specifier.local.name}}`;
        } else if (t.isImportDefaultSpecifier(specifier)) {
          importBlock[`${specifier.local.name}`] = `${path.node.source.value}`;
          printableCode[`${specifier.local.name}`] = `${path.node.source.value} `;
          return specifier.local.name;
        }
      }).join(", ");
    },

    ExpressionStatement(path) {
      const expression = path.get('expression');
      const expressionLeft = expression.get('left');

      if (path.isExpressionStatement() && expression.isAssignmentExpression() && expressionLeft.isMemberExpression()) {
        const docCheck = expressionLeft.toString();

        if (docCheck === `${fileName}.docs`) {
          docCode = expression.toString();
        } else if (docCheck.includes(fileName)) {
          const startIndex = path.node.start;
          const endIndex = path.node.end;
          remainingBlock += fileContent.slice(startIndex, endIndex);
        }
      }
    }

  });
  remainingCode = remainingCode.replace(/__DOCS__/, true);
  remainingCode = remainingCode.replace(/`/g, '\\`').replace(/\$\{/g, '$\\{');
  remainingBlock = remainingBlock.replace(/`/g, '\\`').replace(/\$\{/g, '$\\{');
  const addBractick = `\`
  ${createImportStatements(printableCode)}
  ${remainingCode}

  ${remainingBlock}\`
  `;
  const template = `
  
    ${createImportStatements(importBlock)}
  
    import { LiveProviderv3, LiveEditorv3, LiveErrorv3, LivePreviewv3, Wrapper, EditorWrapper , ErrorWrapper, PreviewWrapper } from '@zohodesk-private/react-live/es/index'

    export default class ${fileName} extends React.Component{
      render(){
        return(
          <LiveProviderv3 needToolBox scope={{import: {${convertKeyToValue(mergeDuplicateValues(printableCode))}}}} code={${addBractick}}>
            <Wrapper>
                <EditorWrapper><LiveEditorv3 /></EditorWrapper>
                <PreviewWrapper><LivePreviewv3 /></PreviewWrapper>
                <LiveErrorv3 needStyle />
            </Wrapper>
          </LiveProviderv3>
        )
      }
    }
  
    ${docCode}
    `;
  return template;
}