"use strict";
var os_1 = require("os");
var Future = require("fibers/future");
var constants_1 = require("../../constants");
var path = require("path");
var constants_2 = require("../../constants");
var ProjectBase = (function () {
    function ProjectBase($cordovaProjectCapabilities, $errors, $fs, $logger, $nativeScriptProjectCapabilities, $options, $projectConstants, $staticConfig) {
        this.$cordovaProjectCapabilities = $cordovaProjectCapabilities;
        this.$errors = $errors;
        this.$fs = $fs;
        this.$logger = $logger;
        this.$nativeScriptProjectCapabilities = $nativeScriptProjectCapabilities;
        this.$options = $options;
        this.$projectConstants = $projectConstants;
        this.$staticConfig = $staticConfig;
        this._shouldSaveProject = false;
        this._hasBuildConfigurations = false;
        this.configurationSpecificData = Object.create(null);
    }
    ProjectBase.prototype.getShouldSaveProject = function () {
        return this._shouldSaveProject;
    };
    ProjectBase.prototype.setShouldSaveProject = function (shouldSaveProject) {
        this._shouldSaveProject = shouldSaveProject;
    };
    Object.defineProperty(ProjectBase.prototype, "projectData", {
        get: function () {
            this.readProjectData().wait();
            return this._projectData;
        },
        set: function (projectData) {
            this._projectData = projectData;
        },
        enumerable: true,
        configurable: true
    });
    ProjectBase.prototype.getProjectDir = function () {
        return Future.fromResult(this.projectDir);
    };
    Object.defineProperty(ProjectBase.prototype, "capabilities", {
        get: function () {
            var projectData = this.projectData;
            if (projectData) {
                if (projectData.Framework && projectData.Framework.toLowerCase() === constants_1.TARGET_FRAMEWORK_IDENTIFIERS.NativeScript.toLowerCase()) {
                    return this.$nativeScriptProjectCapabilities;
                }
                else if (projectData.Framework && projectData.Framework.toLowerCase() === constants_1.TARGET_FRAMEWORK_IDENTIFIERS.Cordova.toLowerCase()) {
                    return this.$cordovaProjectCapabilities;
                }
            }
            return null;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(ProjectBase.prototype, "startPackageActivity", {
        get: function () {
            var projectData = this.projectData;
            return projectData && projectData.Framework ? constants_2.startPackageActivityNames[projectData.Framework.toLowerCase()] : null;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(ProjectBase.prototype, "hasBuildConfigurations", {
        get: function () {
            return this._hasBuildConfigurations;
        },
        enumerable: true,
        configurable: true
    });
    Object.defineProperty(ProjectBase.prototype, "projectInformation", {
        get: function () {
            return {
                projectData: this.projectData,
                configurationSpecificData: this.configurationSpecificData,
                hasBuildConfigurations: this.hasBuildConfigurations,
                configurations: _.keys(this.configurationSpecificData)
            };
        },
        enumerable: true,
        configurable: true
    });
    ProjectBase.prototype.readProjectData = function () {
        var _this = this;
        return (function () {
            var projectDir = _this.getProjectDir().wait();
            _this.setShouldSaveProject(false);
            if (projectDir) {
                var projectFilePath = path.join(projectDir, _this.$projectConstants.PROJECT_FILE);
                try {
                    _this.projectData = _this.getProjectData(projectFilePath);
                    _this.validate();
                    var debugProjectFile = path.join(projectDir, _this.$projectConstants.DEBUG_PROJECT_FILE_NAME);
                    if (_this.$options.debug && !_this.$fs.exists(debugProjectFile).wait()) {
                        _this.$fs.writeJson(debugProjectFile, {}).wait();
                    }
                    var releaseProjectFile = path.join(projectDir, _this.$projectConstants.RELEASE_PROJECT_FILE_NAME);
                    if (_this.$options.release && !_this.$fs.exists(releaseProjectFile).wait()) {
                        _this.$fs.writeJson(releaseProjectFile, {}).wait();
                    }
                    _.each(_this.$fs.enumerateFilesInDirectorySync(projectDir), function (configProjectFile) {
                        var configMatch = path.basename(configProjectFile).match(ProjectBase.CONFIGURATION_FROM_FILE_NAME_REGEX);
                        if (configMatch && configMatch.length > 1) {
                            var configurationName = configMatch[1];
                            var configProjectContent = _this.$fs.readJson(configProjectFile).wait(), configurationLowerCase = configurationName.toLowerCase();
                            _this.configurationSpecificData[configurationLowerCase] = _.merge(_.cloneDeep(_this._projectData), configProjectContent);
                            _this._hasBuildConfigurations = true;
                        }
                    });
                }
                catch (err) {
                    if (err.message === "FUTURE_PROJECT_VER") {
                        _this.$errors.failWithoutHelp("This project is created by a newer version of AppBuilder. Upgrade AppBuilder CLI to work with it.");
                    }
                    _this.$errors.failWithoutHelp("The project file %s is corrupted." + os_1.EOL +
                        "Consider restoring an earlier version from your source control or backup." + os_1.EOL +
                        "To create a new one with the default settings, delete this file and run $ appbuilder init hybrid." + os_1.EOL +
                        "Additional technical information: %s", projectFilePath, err.toString());
                }
                _this.saveProjectIfNeeded();
            }
        }).future()();
    };
    ProjectBase.prototype.getProjectData = function (projectFilePath) {
        var data = this.$fs.readJson(projectFilePath).wait();
        if (data.projectVersion && data.projectVersion.toString() !== "1") {
            this.$errors.fail("FUTURE_PROJECT_VER");
        }
        if (!_.has(data, "Framework")) {
            if (_.has(data, "projectType")) {
                data["Framework"] = data["projectType"];
                delete data["projectType"];
            }
            else {
                data["Framework"] = constants_1.TARGET_FRAMEWORK_IDENTIFIERS.Cordova;
            }
            this.setShouldSaveProject(true);
        }
        return data;
    };
    ProjectBase.VALID_CONFIGURATION_CHARACTERS_REGEX = "[-_A-Za-z0-9]";
    ProjectBase.CONFIGURATION_FROM_FILE_NAME_REGEX = new RegExp("^[.](" + ProjectBase.VALID_CONFIGURATION_CHARACTERS_REGEX + "+?)[.]abproject$", "i");
    return ProjectBase;
}());
exports.ProjectBase = ProjectBase;
