"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
Object.defineProperty(exports, "__esModule", { value: true });
const constants = require("../constants");
const constants_1 = require("../common/constants");
const events_1 = require("events");
const helpers_1 = require("../common/helpers");
class BuildController extends events_1.EventEmitter {
    constructor($analyticsService, $buildArtefactsService, $buildInfoFileService, $fs, $logger, $injector, $mobileHelper, $projectDataService, $projectChangesService, $prepareController) {
        super();
        this.$analyticsService = $analyticsService;
        this.$buildArtefactsService = $buildArtefactsService;
        this.$buildInfoFileService = $buildInfoFileService;
        this.$fs = $fs;
        this.$logger = $logger;
        this.$injector = $injector;
        this.$mobileHelper = $mobileHelper;
        this.$projectDataService = $projectDataService;
        this.$projectChangesService = $projectChangesService;
        this.$prepareController = $prepareController;
    }
    get $platformsDataService() {
        return this.$injector.resolve("platformsDataService");
    }
    prepareAndBuild(buildData) {
        return __awaiter(this, void 0, void 0, function* () {
            yield this.$prepareController.prepare(buildData);
            const result = yield this.build(buildData);
            return result;
        });
    }
    build(buildData) {
        return __awaiter(this, void 0, void 0, function* () {
            this.$logger.info("Building project...");
            const platform = buildData.platform.toLowerCase();
            const projectData = this.$projectDataService.getProjectData(buildData.projectDir);
            const platformData = this.$platformsDataService.getPlatformData(platform, projectData);
            const action = "Build";
            const isForDevice = this.$mobileHelper.isAndroidPlatform(platform) ? null : buildData && buildData.buildForDevice;
            yield this.$analyticsService.trackEventActionInGoogleAnalytics({
                action,
                isForDevice,
                platform,
                projectDir: projectData.projectDir,
                additionalData: `${buildData.release ? constants_1.Configurations.Release : constants_1.Configurations.Debug}_${buildData.clean ? "Clean" : "Incremental"}`
            });
            if (buildData.clean) {
                yield platformData.platformProjectService.cleanProject(platformData.projectRoot);
            }
            const handler = (data) => {
                this.emit(constants.BUILD_OUTPUT_EVENT_NAME, data);
                this.$logger.info(data.data.toString(), { [constants.LoggerConfigData.skipNewLine]: true });
            };
            yield helpers_1.attachAwaitDetach(constants.BUILD_OUTPUT_EVENT_NAME, platformData.platformProjectService, handler, platformData.platformProjectService.buildProject(platformData.projectRoot, projectData, buildData));
            const buildInfoFileDir = platformData.getBuildOutputPath(buildData);
            this.$buildInfoFileService.saveLocalBuildInfo(platformData, buildInfoFileDir);
            this.$logger.info("Project successfully built.");
            const result = yield this.$buildArtefactsService.getLatestAppPackagePath(platformData, buildData);
            if (buildData.copyTo) {
                this.$buildArtefactsService.copyLatestAppPackage(buildData.copyTo, platformData, buildData);
                this.$logger.info(`The build result is located at: ${buildInfoFileDir}`);
            }
            return result;
        });
    }
    buildIfNeeded(buildData) {
        return __awaiter(this, void 0, void 0, function* () {
            let result = null;
            const shouldBuildPlatform = yield this.shouldBuild(buildData);
            if (shouldBuildPlatform) {
                result = yield this.build(buildData);
            }
            return result;
        });
    }
    shouldBuild(buildData) {
        return __awaiter(this, void 0, void 0, function* () {
            const projectData = this.$projectDataService.getProjectData(buildData.projectDir);
            const platformData = this.$platformsDataService.getPlatformData(buildData.platform, projectData);
            const outputPath = buildData.outputPath || platformData.getBuildOutputPath(buildData);
            if (buildData.release && this.$projectChangesService.currentChanges.hasChanges) {
                return true;
            }
            const changesInfo = this.$projectChangesService.currentChanges || (yield this.$projectChangesService.checkForChanges(platformData, projectData, buildData));
            if (changesInfo.changesRequireBuild) {
                return true;
            }
            if (!this.$fs.exists(outputPath)) {
                return true;
            }
            const validBuildOutputData = platformData.getValidBuildOutputData(buildData);
            const packages = this.$buildArtefactsService.getAllAppPackages(outputPath, validBuildOutputData);
            if (packages.length === 0) {
                return true;
            }
            const prepareInfo = this.$projectChangesService.getPrepareInfo(platformData);
            const buildInfo = this.$buildInfoFileService.getLocalBuildInfo(platformData, buildData);
            if (!prepareInfo || !buildInfo) {
                return true;
            }
            if (buildData.clean) {
                return true;
            }
            if (prepareInfo.time === buildInfo.prepareTime) {
                return false;
            }
            return prepareInfo.changesRequireBuildTime !== buildInfo.prepareTime;
        });
    }
}
exports.BuildController = BuildController;
$injector.register("buildController", BuildController);
