'use strict';

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

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

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

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


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

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

    // 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 envTarget (used by remotes)
    const envTarget = innerCommon.getEnvTarget();

    // local saved vars
    let newVersion, pkgCompositeDeps;


    return Promise.resolve()

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

      // FOR UI and REMOTES clone metadata repositories
      .then(() => {
        return innerCommon.cloneMetadataRepos(pkg);
      })


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


      // INSTALL dependencies by type
      .then(() => {
        return installUtils.buildPackage.installRemote(pkg, envTarget);
      })
      .then((compositeDeps) => {
        // storing for later use
        pkgCompositeDeps = compositeDeps;
      })


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

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


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


      // STORING METADATA ASSETS
      .then(() => {
        return innerCommon.storeMetadataAssets(pkg, pkgCompositeDeps);
      })


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


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


      // STORING CENTRALIZED METADATA
      .then(() => {
        // get run duration
        const duration = utils.pipeline.getTimerDuration();

        // store envs + versions for virtual remotes
        return metadataUtils.remotePackage.storeMetadata(pkg, newVersion, pkgCompositeDeps, duration, envTarget);
      })


      // GENERATE DIFF REPORT
      .then(() => {
        let metadata;

        if (envTarget !== 'DEV') {
          return Promise.resolve()
            .then(() => {
              return metadataUtils.remoteHistory.generateDiffCommitsMetadataReport(pkg, envTarget);
            })
            .then((output) => {
              metadata = output;
            })
            .then(() => {
              return utils.notification.package.sendPackageDiffReportMessage(
                pkg,
                metadata.diffsMetadata
              );
            })
            .then(() => {
              return metadataUtils.remoteHistory.storeMetadataHistory(pkg, metadata, newVersion);
            })
            .then(() => {
              if (metadata.commitsMetadata && metadata.commitsMetadata.issues) {
                return metadataUtils.remoteHistory.generatePipelineIssuesList(metadata.commitsMetadata.issues);
              }
            })
            .catch((e) => {
              utils.tools.logError('Error generating diffs report for current remote processed :');
              console.log(e);
            })
          }
      })


      // COMMITING METADATA
      .then(() => {
        return innerCommon.commitMetadata(pkg, newVersion);
      })


      // EXPORT ADDITIONAL PIPELINE VARIABLES
      .then(() => {
        return innerCommon.exportPipelineVariables(pkg);
      })

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

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