'use strict';

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

// UTILS
const utils = require('../../../utils');

// CSDR RELATED
const configUtils = require('../../config/config-utils');
const metadataUtils = require('../../metadata/metadata-utils');
const auditUtils = require('../../audit/audit-utils');
const installUtils = require('../../install/install-utils');

// INNER MODULES
const innerCommon = require('./common');

// ARGS
const { skipInstall, skipAudit } = utils.tools.getArgs();


module.exports.run = () => {
    utils.tools.logBanner('Starting UI pipeline');

    // fetching package from config based on default arg
    const pkg = configUtils.packages.getPackage();

    // checking if the package can be retrieved from args
    if (!pkg.name) {
      utils.tools.logError('ERROR : "package" NOT PROVIDED as argument !!!');
      process.exit(1);
    }

    // Get branches flags
    const branches = innerCommon.getBranches();

    // Get envTarget (used by remotes)
    const envTarget = innerCommon.getEnvTarget();

    // local saved vars
    let newVersion, commitsMetadata;


    return Promise.resolve()

      // RELEASE PACKAGE START
      .then(() => {
        return innerCommon.init(pkg, envTarget);
      })

      // TODO for UI PKG, to store and avoid race-conditions between similar pkg build, find a better way to handle this avoiding this repo
      // clone metadata locks repo repositories
      .then(() => {
        return innerCommon.cloneMetadataLocksRepos(pkg);
      })

      // PRE-RELEASE & COMMON CHECKS
      .then(() => {
        return innerCommon.preReleaseChecks(pkg);
      })

      // FETCHING COMMITS METADATA
      .then(() => {
        return metadataUtils.commit.getMetadata(pkg);
      })
      .then((metadata) => {
        commitsMetadata = metadata;
      })

      // COMMIT METADATA CHECKS
      .then(() => {
        return innerCommon.commitMetadataChecks(pkg);
      })
      .then((metadata) => {
        commitsMetadata = metadata;
      })


      // EXECUTING PRE BUILD SCRIPT IF AVAILABLE
      .then(() => {
        return innerCommon.preBuild(pkg);
      })


      // INSTALL dependencies by type
      .then(() => {
        if (!skipInstall) {
          return Promise.resolve()
            // FETCHING CURRENT PACKAGES & INSTALL
            .then(() => {
              // fetch related project if passed as arguments
              const prj = configUtils.projects.getProject();

              // install the dependencies for current package build
              return installUtils.buildPackage.installPackage(prj, pkg, branches.isMaster);
            })

            // AUDIT DEPENDENCIES
            .then(() => {
              if (!skipAudit) {
                return auditUtils.yarn.audit(pkg);
              }
            })
            .catch((e) => {
              throw e;
            })
        }
      })


      // BUILD PACKAGE
      .then(() => {
        return utils.buildPackage.build(pkg, branches.isMaster);
      })


      // EXECUTING SONAR ANALYSIS
      .then(() => {
        return utils.sonar.run(pkg, branches.isMaster);
      })


      // GENERATE and UPDATE new version
      .then(() => {
        return innerCommon.updateVersion(pkg, commitsMetadata);
      })
      .then((version) => {
        // storing version for later use
        newVersion = version;
      })


      // GENERATE CHANGELOG
      .then(() => {
        return innerCommon.generateChangelog(pkg, newVersion, commitsMetadata);
      })


      // EXECUTING GLOBAL POST BUILD
      .then(() => {
        return innerCommon.postBuild(pkg, newVersion);
      })


      // PUBLISH PACKAGE
      .then(() => {
        return utils.publish.publish(pkg);
      })


      // EXECUTING POST PUBLISH SCRIPT IF AVAILABLE
      .then(() => {
        return utils.publish.postPublish(pkg);
      })


      // GIT OPERATIONS
      .then(() => {
        return innerCommon.runGitOperations(pkg, newVersion);
      })


      // SEND SUCCESS NOTIFICATION
      .then(() => {
        return innerCommon.sendSuccessNotification(pkg, newVersion, commitsMetadata)
          .then(() => {
            return innerCommon.close(pkg);
          });
      })

      // SEND ERROR NOTIFICATION
      .catch((e) => {
        return innerCommon.sendErrorNotification(pkg, e, commitsMetadata)
          .then(() => {
            return innerCommon.close(pkg);
          })
          .then(() => {
            process.exit(1);
          })
      })
}
