"use strict";
var __extends = (this && this.__extends) || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var events_1 = require("events");
var constants_1 = require("../constants");
var ApplicationManagerBase = (function (_super) {
    __extends(ApplicationManagerBase, _super);
    function ApplicationManagerBase($logger, $hooksService) {
        _super.call(this);
        this.$logger = $logger;
        this.$hooksService = $hooksService;
        this.lastAvailableDebuggableAppViews = {};
        this.isChecking = false;
    }
    ApplicationManagerBase.prototype.reinstallApplication = function (appIdentifier, packageFilePath) {
        var _this = this;
        return (function () {
            _this.uninstallApplication(appIdentifier).wait();
            _this.installApplication(packageFilePath).wait();
        }).future()();
    };
    ApplicationManagerBase.prototype.restartApplication = function (appIdentifier, bundleExecutable, framework) {
        var _this = this;
        return (function () {
            _this.stopApplication(bundleExecutable || appIdentifier).wait();
            _this.startApplication(appIdentifier, framework).wait();
        }).future()();
    };
    ApplicationManagerBase.prototype.isApplicationInstalled = function (appIdentifier) {
        var _this = this;
        return (function () {
            if (!_this.lastInstalledAppIdentifiers || !_this.lastInstalledAppIdentifiers.length) {
                _this.checkForApplicationUpdates().wait();
            }
            return _.includes(_this.lastInstalledAppIdentifiers, appIdentifier);
        }).future()();
    };
    ApplicationManagerBase.prototype.checkForApplicationUpdates = function () {
        var _this = this;
        return (function () {
            if (!_this.isChecking) {
                try {
                    _this.isChecking = true;
                    var currentlyInstalledAppIdentifiers = _this.getInstalledApplications().wait();
                    var previouslyInstalledAppIdentifiers = _this.lastInstalledAppIdentifiers || [];
                    var newAppIdentifiers = _.difference(currentlyInstalledAppIdentifiers, previouslyInstalledAppIdentifiers);
                    var removedAppIdentifiers = _.difference(previouslyInstalledAppIdentifiers, currentlyInstalledAppIdentifiers);
                    _this.lastInstalledAppIdentifiers = currentlyInstalledAppIdentifiers;
                    _.each(newAppIdentifiers, function (appIdentifier) { return _this.emit("applicationInstalled", appIdentifier); });
                    _.each(removedAppIdentifiers, function (appIdentifier) { return _this.emit("applicationUninstalled", appIdentifier); });
                    _this.checkForAvailableDebuggableAppsChanges().wait();
                }
                finally {
                    _this.isChecking = false;
                }
            }
        }).future()();
    };
    ApplicationManagerBase.prototype.tryStartApplication = function (appIdentifier, framework) {
        var _this = this;
        return (function () {
            try {
                if (_this.canStartApplication()) {
                    _this.startApplication(appIdentifier, framework).wait();
                }
            }
            catch (err) {
                _this.$logger.trace("Unable to start application " + appIdentifier + ". Error is: " + err.message);
            }
        }).future()();
    };
    ApplicationManagerBase.prototype.checkForAvailableDebuggableAppsChanges = function () {
        var _this = this;
        return (function () {
            var currentlyAvailableDebuggableApps = _this.getDebuggableApps().wait();
            var previouslyAvailableDebuggableApps = _this.lastAvailableDebuggableApps || [];
            var newAvailableDebuggableApps = _.differenceBy(currentlyAvailableDebuggableApps, previouslyAvailableDebuggableApps, "appIdentifier");
            var notAvailableAppsForDebugging = _.differenceBy(previouslyAvailableDebuggableApps, currentlyAvailableDebuggableApps, "appIdentifier");
            _this.lastAvailableDebuggableApps = currentlyAvailableDebuggableApps;
            _.each(newAvailableDebuggableApps, function (appInfo) {
                _this.emit("debuggableAppFound", appInfo);
            });
            _.each(notAvailableAppsForDebugging, function (appInfo) {
                _this.emit("debuggableAppLost", appInfo);
                if (_.has(_this.lastAvailableDebuggableAppViews, appInfo.appIdentifier)) {
                    delete _this.lastAvailableDebuggableAppViews[appInfo.appIdentifier];
                }
            });
            var cordovaDebuggableAppIdentifiers = _(currentlyAvailableDebuggableApps)
                .filter(function (c) { return c.framework === constants_1.TARGET_FRAMEWORK_IDENTIFIERS.Cordova; })
                .map(function (c) { return c.appIdentifier; })
                .value();
            var currentlyAvailableAppViews = _this.getDebuggableAppViews(cordovaDebuggableAppIdentifiers).wait();
            _.each(currentlyAvailableAppViews, function (currentlyAvailableViews, appIdentifier) {
                var previouslyAvailableViews = _this.lastAvailableDebuggableAppViews[appIdentifier];
                var newAvailableViews = _.differenceBy(currentlyAvailableViews, previouslyAvailableViews, "id");
                var notAvailableViews = _.differenceBy(previouslyAvailableViews, currentlyAvailableViews, "id");
                _.each(notAvailableViews, function (debugWebViewInfo) {
                    _this.emit("debuggableViewLost", appIdentifier, debugWebViewInfo);
                });
                _.each(newAvailableViews, function (debugWebViewInfo) {
                    _this.emit("debuggableViewFound", appIdentifier, debugWebViewInfo);
                });
                var keptViews = _.differenceBy(currentlyAvailableViews, newAvailableViews, "id");
                _.each(keptViews, function (view) {
                    var previousTimeViewInfo = _.find(previouslyAvailableViews, function (previousView) { return previousView.id === view.id; });
                    if (!_.isEqual(view, previousTimeViewInfo)) {
                        _this.emit("debuggableViewChanged", appIdentifier, view);
                    }
                });
                _this.lastAvailableDebuggableAppViews[appIdentifier] = currentlyAvailableViews;
            });
        }).future()();
    };
    return ApplicationManagerBase;
}(events_1.EventEmitter));
exports.ApplicationManagerBase = ApplicationManagerBase;
