'use strict';

// GLOBAL
const path = require('path');
const execa = require('execa');
const fs = require('fs');

// LOCAL
const tools = require('../../tools');
const notificationUtils = require('../../notification/notification-utils');

// FETCH ARGS
let { skipCompile, dryRun } = tools.getArgs();


const compileSassFileNodeSass = (folder, filename, isNodeSassTildeImporterActive) => {

  const filePath = path.join(folder, 'styles', filename);

  tools.logInfo(`Compiling ${filePath}.scss...`);

  return Promise.resolve()
    .then(() => {
      tools.logInfo('Compiling SCSS...');

      if (isNodeSassTildeImporterActive !== false) {
        tools.logInfo('building with tilde importer');

        return execa('node-sass', [
          filePath + '.scss',
          filePath + '.temp.css',
          '--importer',
          './node_modules/node-sass-tilde-importer',
          '--output-style',
          'compressed',
          '--source-map',
          true,
          '--source-map-contents'
        ]);

      } else {
        tools.logInfo('building without tilde importer');

        return execa('node-sass', [
          filePath + '.scss',
          filePath + '.temp.css',
          '--importer',
          '--output-style',
          'compressed',
          '--source-map',
          true,
          '--source-map-contents'
        ]);

      }
    })

    .then((output) => {
      // console.log(output);
      console.log('Size ::: ' + fs.statSync(filePath + '.temp.css').size);
    })

    .then(() => {
      tools.logInfo('Running postCss over generated css file...');

      return execa('postcss', [
        filePath + '.temp.css',
        '--config',
        path.join(__dirname, 'postcss.config.js'),
        '--no-map',
        '--verbose',
        '--output',
        filePath + '.css'
      ]);
    })

    .then((output) => {
      // console.log(output);
      tools.logInfo('forcing utf-8 charset');
      let fileContent = tools.getFileContent(`${filePath}.css`);
      fileContent = '@charset "UTF-8";' + fileContent;
      tools.writeFileContent(`${filePath}.css`, fileContent);

      console.log('Size ::: ' + fs.statSync(filePath + '.css').size);

      tools.logSuccess(`OK ==> generated ${filePath}.css`);
    })

    .then(() => {
      tools.remove(filePath + '.temp.css');
      tools.remove(filePath + '.temp.css.map');
    })
    .catch((e) => {
      console.log(e);
      throw e;
    })
}



const compileSassFileDartSass = (folder, filename) => {
  const filePath = path.join(folder, 'styles', filename);

  tools.logInfo(`Compiling ${filePath}.scss...`);

  return Promise.resolve()
    .then(() => {
      tools.logInfo('Compiling SCSS...');

      const sass = require('sass');

      return sass.renderSync({
        file: filePath + '.scss',
        outFile: filePath + '.temp.css',
        sourceMap: true,
        sourceMapContents: true,
        sourceMapEmbed: true,
        includePaths: [
          path.resolve(process.cwd(), 'node_modules'),
        ],
      });
    })

    .then((sassResult) => {
      const finalDest = filePath + '.css';

      const cssnano = require('cssnano');
      const autoprefixer = require('autoprefixer');
      const postcss = require('postcss');

      const plugins = [];

      plugins.push(autoprefixer({
        grid: 'no-autoplace',
      }));
      plugins.push(cssnano({ safe: true }));

      return postcss(plugins)
      .process(sassResult.css, {
        map: { inline: false, prev: sassResult.map.toString() },
        from: filePath + '.scss',
        to: finalDest,
      })
      .then((postcssResult) => {
        // fs.mkdirSync(path.dirname(dest), { recursive: true });
        fs.writeFileSync(finalDest, postcssResult.css);

        if (postcssResult.map) {
          fs.writeFileSync(`${finalDest}.map`, postcssResult.map.toString());
        }
      });
    })

    .then((output) => {
      // console.log(output);
      console.log('Size ::: ' + fs.statSync(filePath + '.css').size);

      tools.logSuccess(`OK ==> generated ${filePath}.css`);
    })

    .then(() => {
      tools.remove(filePath + '.temp.css');
      tools.remove(filePath + '.temp.css.map');
    })

    .catch((e) => {
      console.log(e);
      throw e;
    })
}



const compileSassFile = (pkg, folder, filename, isNodeSassTildeImporterActive) => {
  return Promise.resolve()
    .then(() => {
      if (
          pkg.build &&
          (
            pkg.build.euiVersion === '13.x' ||
            pkg.build.euiVersion === '14.x' ||
            pkg.build.euiVersion === '15.x' ||
            pkg.build.euiVersion === '16.x' ||
            pkg.build.euiVersion === '17.x' ||
            pkg.build.euiVersion === '18.x' ||
            pkg.build.euiVersion === '19.x'
          )) {
        return compileSassFileDartSass(folder, filename);

      } else {
        return compileSassFileNodeSass(folder, filename, isNodeSassTildeImporterActive);
      }
    })

    .catch((e) => {
      console.log(e);
      throw e;
    })
}



module.exports.build = (pkg) => {
  tools.logInfo('Building STYLES package...');

  const srcFolder = pkg.paths.src;
  const srcOutFolder = path.join(pkg.paths.dist, 'src');
  const tmpFolder = path.join(pkg.paths.dist, 'tmp');
  const tmpFolderStyles = path.join(tmpFolder, 'styles');
  const distFolder = path.join(pkg.paths.dist, 'dist');

  if (!skipCompile) {

    return Promise.resolve()
      .then(() => {
        return tools.rimraf(tmpFolder);
      })
      .then(() => {
        return tools.rimraf(distFolder);
      })
      .then(() => {
        return tools.copydir(srcFolder, tmpFolder);
      })
      .then(() => {
        console.log('Temp copy succeeded.');
      })
      .then(() => {
        if (pkg.build.euiVersion !== '18.x' && pkg.build.euiVersion !== '19.x') {
          return tools.copydir(srcFolder, srcOutFolder);
        }
      })
      .then(() => {
        console.log('Sources copy succeeded.')
      })
      .then(() => Promise.resolve().then(() => {
        tools.logInfo('Processing stylesheets entries : ');
        console.log(pkg.stylesheets);

        return pkg.stylesheets.reduce((promise, file) => {
          return promise.then(() => (
            compileSassFile(pkg, tmpFolder, file, pkg.build && pkg.build.isNodeSassTildeImporterActive)
          )).catch((e) => {
            console.log(e);
            throw e;
          });
        }, Promise.resolve());
      }))
      .then(() => {
        if (pkg.build.euiVersion !== '18.x' && pkg.build.euiVersion !== '19.x') {
          return tools.copydir(tmpFolder, distFolder, true, `**/*.css`);
        } else {
          return tools.copydir(tmpFolderStyles, distFolder, true, `**/*.css`);
        }
      })
      .then(() => {
        if (pkg.build.euiVersion !== '18.x' && pkg.build.euiVersion !== '19.x') {
          return tools.copydir(tmpFolder, distFolder, true, `**/*.map`);
        } else {
          return tools.copydir(tmpFolderStyles, distFolder, true, `**/*.map`);
        }
      })
      .then(() => {
        if (pkg.build.publishSourceFolders) {
          return pkg.build.publishSourceFolders.reduce((promise, folder) => {
            return promise.then(() => (
              tools.copydir(path.join(srcFolder, folder), path.join(distFolder, folder))
            )).catch((e) => {
              console.log(e);
              throw e;
            });
          }, Promise.resolve());
        }
      })
      .then(() => {
        console.log('Output CSS copy succeeded');
      })
      .then(() => {
        return tools.copydir(srcFolder + '/assets', distFolder + '/assets');
      })
      .then(() => {
        if (pkg.build && pkg.build.skipPublicationFolders) {
          return pkg.build.skipPublicationFolders.reduce((promise, folder) => {
            return promise.then(() => (
              tools.rimraf(path.join(distFolder, folder))
            )).catch((e) => {
              console.log(e);
              throw e;
            });
          }, Promise.resolve());
        }
      })
      .then(() => {
        console.log('assets copy succeeded');
        tools.copy(path.join(pkg.paths.root, 'package.json'), path.join(pkg.paths.dist, 'package.json'));
        tools.copy(path.join(pkg.paths.root, 'README.md'), path.join(pkg.paths.dist, 'README.md'));
        tools.copy(path.join(pkg.paths.root, 'LICENSE'), path.join(pkg.paths.dist, 'LICENSE'));
      })
      .then(() => {
        return tools.rimraf(tmpFolder);
      })
      .then(() => {
        return notificationUtils.package.sendPackageMessage({
          package: pkg
        })
      })
      .then(() => {
        tools.logInfo('Executing post-build.js script if present in package');
        const postbuildScript = path.join(pkg.paths.root, 'post-build.js');
        if (!dryRun && tools.isFileExists(postbuildScript)) {
          return tools.runScript(`node ${postbuildScript}`);
        } else {
          tools.logInfo('DRY-RUN OR post-build.js script not found in package root --- SKIPPING');
        }
      })

      .catch((e) => {
        throw e;
      })
  }
}

