"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 path = require("path");
const semver = require("semver");
const util = require("util");
const preview_app_constants_1 = require("./preview-app-constants");
const constants_1 = require("../../../common/constants");
const constants_2 = require("../../../constants");
class PreviewAppPluginsService {
    constructor($fs, $logger, $pluginsService) {
        this.$fs = $fs;
        this.$logger = $logger;
        this.$pluginsService = $pluginsService;
        this.previewAppVersionWarnings = {};
    }
    comparePluginsOnDevice(data, device) {
        return __awaiter(this, void 0, void 0, function* () {
            if (!this.previewAppVersionWarnings[device.previewAppVersion]) {
                const devicePlugins = this.getDevicePlugins(device);
                const localPlugins = this.getLocalPlugins(data.projectDir);
                const warnings = _.keys(localPlugins)
                    .map(localPlugin => {
                    const localPluginVersion = localPlugins[localPlugin];
                    const devicePluginVersion = devicePlugins[localPlugin];
                    return this.getWarningForPlugin(data, localPlugin, localPluginVersion, devicePluginVersion, device);
                })
                    .filter(item => !!item);
                this.previewAppVersionWarnings[device.previewAppVersion] = warnings;
            }
            this.previewAppVersionWarnings[device.previewAppVersion].map(warning => this.$logger.warn(warning));
        });
    }
    getExternalPlugins(device) {
        const devicePlugins = this.getDevicePlugins(device);
        const result = _.keys(devicePlugins)
            .filter(plugin => plugin.indexOf("nativescript") !== -1)
            .filter(plugin => !_.includes(["nativescript-angular", "nativescript-vue", "nativescript-intl", "nativescript-theme-core"], plugin));
        result.push(...["tns-core-modules", "tns-core-modules-widgets"]);
        return result;
    }
    getDevicePlugins(device) {
        try {
            return JSON.parse(device.plugins);
        }
        catch (err) {
            this.$logger.trace(`Error while parsing plugins from device ${device.id}. Error is ${err.message}`);
            return {};
        }
    }
    getLocalPlugins(projectDir) {
        const projectFilePath = path.join(projectDir, constants_2.PACKAGE_JSON_FILE_NAME);
        try {
            return this.$fs.readJson(projectFilePath).dependencies;
        }
        catch (err) {
            this.$logger.trace(`Error while parsing ${projectFilePath}. Error is ${err.message}`);
            return {};
        }
    }
    getWarningForPlugin(data, localPlugin, localPluginVersion, devicePluginVersion, device) {
        if (data && data.appFilesUpdaterOptions && data.appFilesUpdaterOptions.bundle) {
            const pluginPackageJsonPath = path.join(data.projectDir, constants_1.NODE_MODULES_DIR_NAME, localPlugin, constants_2.PACKAGE_JSON_FILE_NAME);
            const isNativeScriptPlugin = this.$pluginsService.isNativeScriptPlugin(pluginPackageJsonPath);
            if (!isNativeScriptPlugin || (isNativeScriptPlugin && !this.hasNativeCode(localPlugin, device.platform, data.projectDir))) {
                return null;
            }
        }
        return this.getWarningForPluginCore(localPlugin, localPluginVersion, devicePluginVersion, device.id);
    }
    getWarningForPluginCore(localPlugin, localPluginVersion, devicePluginVersion, deviceId) {
        this.$logger.trace(`Comparing plugin ${localPlugin} with localPluginVersion ${localPluginVersion} and devicePluginVersion ${devicePluginVersion}`);
        if (devicePluginVersion) {
            const localPluginVersionData = semver.coerce(localPluginVersion);
            const devicePluginVersionData = semver.coerce(devicePluginVersion);
            if (localPluginVersionData.major !== devicePluginVersionData.major) {
                return util.format(preview_app_constants_1.PluginComparisonMessages.LOCAL_PLUGIN_WITH_DIFFERENCE_IN_MAJOR_VERSION, localPlugin, localPluginVersion, devicePluginVersion);
            }
            else if (localPluginVersionData.minor > devicePluginVersionData.minor) {
                return util.format(preview_app_constants_1.PluginComparisonMessages.LOCAL_PLUGIN_WITH_GREATHER_MINOR_VERSION, localPlugin, localPluginVersion, devicePluginVersion);
            }
            return null;
        }
        return util.format(preview_app_constants_1.PluginComparisonMessages.PLUGIN_NOT_INCLUDED_IN_PREVIEW_APP, localPlugin, deviceId);
    }
    hasNativeCode(localPlugin, platform, projectDir) {
        const nativeFolderPath = path.join(projectDir, constants_1.NODE_MODULES_DIR_NAME, localPlugin, constants_2.PLATFORMS_DIR_NAME, platform.toLowerCase());
        return this.$fs.exists(nativeFolderPath) && !this.$fs.isEmptyDir(nativeFolderPath);
    }
}
exports.PreviewAppPluginsService = PreviewAppPluginsService;
$injector.register("previewAppPluginsService", PreviewAppPluginsService);
