'use strict';

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

// LOCAL
const tools = require('../../tools');
const configUtils = require('../../../csdr/config/config-utils');

// INNER MODULES
const innerNodeJs = require('./nodeJs');
const innerMaven = require('./maven');
const innerStyles = require('./styles');
const innerAngular = require('./angular');
const innerElement = require('./element');


// RE-EXPORTS MODULES
module.exports.element = innerElement;

// FETCH ARGS
const { dryRun } = tools.getArgs();


const buildBackend = (pkg, isMaster) => {

  return Promise.resolve()
    .then(() => {
      if (pkg.build.nodeJs) {
        return innerNodeJs.build(pkg, isMaster);

      } else {
        return innerMaven.build(pkg, isMaster);
      }
    })
    .catch((e) => {
      throw e;
    })
}




const buildCore = (pkg, isMaster) => {
  tools.logTitle(`Building package : ${pkg.name}...`);

  if (pkg.build && pkg.build.exec === false) {
    tools.logInfo(`Build not executed for "${pkg.name}"`);
    return Promise.resolve();
  }

  if (pkg.stylesPackage) {
    return innerStyles.build(pkg);

  } else if (pkg.backend) {
    return buildBackend(pkg, isMaster);

  } else if (pkg.element) {
    return innerElement.build(pkg, isMaster);

  } else if (pkg.nodeJs) {
    return innerNodeJs.build(pkg, isMaster);

  } else {
    return innerAngular.build(pkg, isMaster);
  }
}







module.exports.build = (pkg, isMaster) => {

  return Promise.resolve()

    // checking package relation
    .then(() => {

      if (!pkg.parent) {
        // building normal package without linked children
        return buildCore(pkg, isMaster);

      } else {

        // handling sub-packages
        return Promise.resolve()
          .then(() => {
            var linkedPackages = Object.keys(pkg.packages).map(p => {
              const pkg = configUtils.packages.getPackage(p);
              return pkg;
            }).filter(p => {
              return ((p.build && p.build.exec !== false) || !p.build)
            });

            const outputPackages = tools.removeArrayDuplicates(linkedPackages, 'name');
            tools.logInfo('found linked packages : ');
            outputPackages.map(p => {
              console.log(p.name);
            });
            return outputPackages;
          })

          .then((linkedPackages) => Promise.resolve().then(() => {
            return linkedPackages.reduce((promise, pkg) => {
              return promise.then(() => (
                buildCore(pkg, isMaster)
              ));
            }, Promise.resolve());
          }))

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

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



module.exports.preBuild = (pkg) => {
  tools.logTitle('Executing package pre-build script');

  return Promise.resolve()
    .then(() => {
      const prebuildScript = path.join(pkg.paths.root, 'pre-build.js');
      if (!dryRun && tools.isFileExists(prebuildScript)) {
        return tools.runScript(`node ${prebuildScript}`);
      } else {
        tools.logInfo('DRY-RUN or pre-build script not found in package root --- skipping');
      }
    })
    .then(() => {
      tools.logSuccess();
    })

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




module.exports.postBuild = (pkg) => {
  tools.logTitle('Executing package post-build script');

  return Promise.resolve()
    .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');
      }
    })

    // Clean up temporary sonar generated folder and files
    .then(() => {
      tools.logInfo('Cleaning sonar temporary assets if exist');
      const sonarTempPath = path.join(pkg.paths.root, '.scannerwork');
      if (tools.isDirExists(sonarTempPath)) {
        return tools.rimraf(sonarTempPath);
      }
    })

    .then(() => {
      tools.logSuccess();
    })
    .catch((e) => {
      throw e;
    })
}


module.exports.buildSubEntry = (pkg, subEntry) => {
  return Promise.resolve()
    .then(() => {
      tools.logInfo(`Building sub-entry : ${subEntry} of package : ${pkg.name}`);
      // console.log(pkg);
      return tools.getFilesGlob(pkg.paths.root, `**/package.json`);
    })

    .then((files) => {
      // console.log(files);

      if (files.length === 0) {
        tools.logWarning(`no sub-entries found within package ${pkg.name}`);
        return;

      } else {
        let subEntryPath = files.filter((f) => {
          return f.indexOf(subEntry) > -1;
        })[0];

        if (!subEntryPath) {
          tools.logWarning(`${subEntry} can't be found in sub-folders of package (must contains package.json file for sub-entry definition)`);
          return;

        } else {
          subEntryPath = subEntryPath.replace('/ng-package.json', '');
          tools.logInfo(`${subEntryPath} found... injecting angular.json for sub entry`);

          return configUtils.angular.registerAngularPackageSubEntry(subEntry, subEntryPath, pkg);
        };
      }
    })
    .then(() => {
      let packageEuiVersion = configUtils.packages.getPackageEuiVersion(pkg);
      const packageEuiVersionNumber = parseInt(packageEuiVersion);

      if (packageEuiVersionNumber >= 15) {
        const { skipTest } = tools.getArgs();

        if (!skipTest) {
          tools.logInfo('Testing...');
          const ng = path.resolve(process.cwd(), 'node_modules', '@angular', 'cli', 'bin', 'ng');
          let args = ['--max_old_space_size=8096', ng, 'test', subEntry, '--code-coverage', '--watch=false'];
          tools.logInfo(`running ng test : with args: ${args} on folder : ${pkg.paths.root}`);
          return execa('node', args, { cwd: pkg.paths.root, stdio: 'inherit' });
        }
      }
    })
    .then(() => {
      const ng = path.resolve(process.cwd(), 'node_modules', '@angular', 'cli', 'bin', 'ng');

      let args = ['--max_old_space_size=8096', ng, 'build', subEntry];

      return execa('node', args, { cwd: pkg.paths.root, stdio: 'inherit' });
    })

    .then(() => {
      tools.logSuccess();
    })
    .catch((e) => {
      throw e;
    })
}
