"use strict";
var core_1 = require('@angular/core');
var query_params_1 = require('./query-params');
var dom_1 = require('../util/dom');
var registry_1 = require('./registry');
var Platform = (function () {
    function Platform() {
        var _this = this;
        this._versions = {};
        this._onResizes = [];
        this._bbActions = [];
        this._platforms = [];
        this.backButton = new core_1.EventEmitter();
        this.pause = new core_1.EventEmitter();
        this.resume = new core_1.EventEmitter();
        this._readyPromise = new Promise(function (res) { _this._readyResolve = res; });
        this.backButton.subscribe(function () {
            console.debug('hardware back button');
            _this.runBackButtonAction();
        });
    }
    Platform.prototype.setZone = function (zone) {
        this.zone = zone;
    };
    Platform.prototype.is = function (platformName) {
        return (this._platforms.indexOf(platformName) > -1);
    };
    Platform.prototype.platforms = function () {
        return this._platforms;
    };
    Platform.prototype.versions = function () {
        return this._versions;
    };
    Platform.prototype.version = function () {
        for (var platformName in this._versions) {
            if (this._versions[platformName]) {
                return this._versions[platformName];
            }
        }
        return {};
    };
    Platform.prototype.ready = function () {
        return this._readyPromise;
    };
    Platform.prototype.triggerReady = function (readySource) {
        var _this = this;
        this.zone.run(function () {
            _this._readyResolve(readySource);
        });
    };
    Platform.prototype.prepareReady = function () {
        var _this = this;
        dom_1.ready(function () {
            _this.triggerReady('dom');
        });
    };
    Platform.prototype.setDir = function (dir, updateDocument) {
        this._dir = (dir || '').toLowerCase();
        if (updateDocument !== false) {
            document.documentElement.setAttribute('dir', dir);
        }
    };
    Platform.prototype.dir = function () {
        return this._dir;
    };
    Platform.prototype.isRTL = function () {
        return (this._dir === 'rtl');
    };
    Platform.prototype.setLang = function (language, updateDocument) {
        this._lang = language;
        if (updateDocument !== false) {
            document.documentElement.setAttribute('lang', language);
        }
    };
    Platform.prototype.lang = function () {
        return this._lang;
    };
    Platform.prototype.exitApp = function () { };
    Platform.prototype.registerBackButtonAction = function (fn, priority) {
        var _this = this;
        if (priority === void 0) { priority = 0; }
        var action = { fn: fn, priority: priority };
        this._bbActions.push(action);
        return function () {
            var index = _this._bbActions.indexOf(action);
            if (index > -1) {
                _this._bbActions.splice(index, 1);
            }
        };
    };
    Platform.prototype.runBackButtonAction = function () {
        var winner = null;
        this._bbActions.forEach(function (action) {
            if (!winner || action.priority >= winner.priority) {
                winner = action;
            }
        });
        winner && winner.fn && winner.fn();
    };
    Platform.prototype.setUserAgent = function (userAgent) {
        this._ua = userAgent;
    };
    Platform.prototype.setQueryParams = function (queryParams) {
        this._qp = queryParams;
    };
    Platform.prototype.userAgent = function () {
        return this._ua || '';
    };
    Platform.prototype.setNavigatorPlatform = function (navigatorPlatform) {
        this._bPlt = navigatorPlatform;
    };
    Platform.prototype.navigatorPlatform = function () {
        return this._bPlt || '';
    };
    Platform.prototype.width = function () {
        return dom_1.windowDimensions().width;
    };
    Platform.prototype.height = function () {
        return dom_1.windowDimensions().height;
    };
    Platform.prototype.isPortrait = function () {
        return this.width() < this.height();
    };
    Platform.prototype.isLandscape = function () {
        return !this.isPortrait();
    };
    Platform.prototype.windowResize = function () {
        var self = this;
        clearTimeout(self._resizeTm);
        self._resizeTm = setTimeout(function () {
            dom_1.flushDimensionCache();
            for (var i = 0; i < self._onResizes.length; i++) {
                try {
                    self._onResizes[i]();
                }
                catch (e) {
                    console.error(e);
                }
            }
        }, 200);
    };
    Platform.prototype.onResize = function (cb) {
        var self = this;
        self._onResizes.push(cb);
        return function () {
            var index = self._onResizes.indexOf(cb);
            if (index > -1) {
                self._onResizes.splice(index, 1);
            }
        };
    };
    Platform.register = function (platformConfig) {
        platformRegistry[platformConfig.name] = platformConfig;
    };
    Platform.registry = function () {
        return platformRegistry;
    };
    Platform.get = function (platformName) {
        return platformRegistry[platformName] || {};
    };
    Platform.setDefault = function (platformName) {
        platformDefault = platformName;
    };
    Platform.prototype.testQuery = function (queryValue, queryTestValue) {
        var valueSplit = queryValue.toLowerCase().split(';');
        return valueSplit.indexOf(queryTestValue) > -1;
    };
    Platform.prototype.testNavigatorPlatform = function (navigatorPlatformExpression) {
        var rgx = new RegExp(navigatorPlatformExpression, 'i');
        return rgx.test(this._bPlt);
    };
    Platform.prototype.matchUserAgentVersion = function (userAgentExpression) {
        if (this._ua && userAgentExpression) {
            var val = this._ua.match(userAgentExpression);
            if (val) {
                return {
                    major: val[1],
                    minor: val[2]
                };
            }
        }
    };
    Platform.prototype.isPlatformMatch = function (queryStringName, userAgentAtLeastHas, userAgentMustNotHave) {
        if (userAgentMustNotHave === void 0) { userAgentMustNotHave = []; }
        var queryValue = this._qp.get('ionicplatform');
        if (queryValue) {
            return this.testQuery(queryValue, queryStringName);
        }
        userAgentAtLeastHas = userAgentAtLeastHas || [queryStringName];
        var userAgent = this._ua.toLowerCase();
        for (var i = 0; i < userAgentAtLeastHas.length; i++) {
            if (userAgent.indexOf(userAgentAtLeastHas[i]) > -1) {
                for (var j = 0; j < userAgentMustNotHave.length; j++) {
                    if (userAgent.indexOf(userAgentMustNotHave[j]) > -1) {
                        return false;
                    }
                }
                return true;
            }
        }
        return false;
    };
    Platform.prototype.load = function () {
        var rootPlatformNode;
        var enginePlatformNode;
        var tmpPlatform;
        for (var platformName in platformRegistry) {
            tmpPlatform = this.matchPlatform(platformName);
            if (tmpPlatform) {
                if (tmpPlatform.isEngine) {
                    enginePlatformNode = tmpPlatform;
                }
                else if (!rootPlatformNode || tmpPlatform.depth > rootPlatformNode.depth) {
                    rootPlatformNode = tmpPlatform;
                }
            }
        }
        if (!rootPlatformNode) {
            rootPlatformNode = new PlatformNode(platformDefault);
        }
        if (rootPlatformNode) {
            if (enginePlatformNode) {
                enginePlatformNode.child = rootPlatformNode;
                rootPlatformNode.parent = enginePlatformNode;
                rootPlatformNode = enginePlatformNode;
            }
            var platformNode = rootPlatformNode;
            while (platformNode) {
                insertSuperset(platformNode);
                platformNode = platformNode.child;
            }
            platformNode = rootPlatformNode.parent;
            while (platformNode) {
                rootPlatformNode = platformNode;
                platformNode = platformNode.parent;
            }
            platformNode = rootPlatformNode;
            while (platformNode) {
                platformNode.initialize(this);
                this._platforms.push(platformNode.name);
                this._versions[platformNode.name] = platformNode.version(this);
                platformNode = platformNode.child;
            }
        }
        if (this._platforms.indexOf('mobile') > -1 && this._platforms.indexOf('cordova') === -1) {
            this._platforms.push('mobileweb');
        }
    };
    Platform.prototype.matchPlatform = function (platformName) {
        var platformNode = new PlatformNode(platformName);
        var rootNode = platformNode.getRoot(this);
        if (rootNode) {
            rootNode.depth = 0;
            var childPlatform = rootNode.child;
            while (childPlatform) {
                rootNode.depth++;
                childPlatform = childPlatform.child;
            }
        }
        return rootNode;
    };
    return Platform;
}());
exports.Platform = Platform;
function insertSuperset(platformNode) {
    var supersetPlaformName = platformNode.superset();
    if (supersetPlaformName) {
        var supersetPlatform = new PlatformNode(supersetPlaformName);
        supersetPlatform.parent = platformNode.parent;
        supersetPlatform.child = platformNode;
        if (supersetPlatform.parent) {
            supersetPlatform.parent.child = supersetPlatform;
        }
        platformNode.parent = supersetPlatform;
    }
}
var PlatformNode = (function () {
    function PlatformNode(platformName) {
        this.c = Platform.get(platformName);
        this.name = platformName;
        this.isEngine = this.c.isEngine;
    }
    PlatformNode.prototype.settings = function () {
        return this.c.settings || {};
    };
    PlatformNode.prototype.superset = function () {
        return this.c.superset;
    };
    PlatformNode.prototype.isMatch = function (p) {
        return this.c.isMatch && this.c.isMatch(p) || false;
    };
    PlatformNode.prototype.initialize = function (platform) {
        this.c.initialize && this.c.initialize(platform);
    };
    PlatformNode.prototype.version = function (p) {
        if (this.c.versionParser) {
            var v = this.c.versionParser(p);
            if (v) {
                var str = v.major + '.' + v.minor;
                return {
                    str: str,
                    num: parseFloat(str),
                    major: parseInt(v.major, 10),
                    minor: parseInt(v.minor, 10)
                };
            }
        }
    };
    PlatformNode.prototype.getRoot = function (p) {
        if (this.isMatch(p)) {
            var parents = this.getSubsetParents(this.name);
            if (!parents.length) {
                return this;
            }
            var platformNode = null;
            var rootPlatformNode = null;
            for (var i = 0; i < parents.length; i++) {
                platformNode = new PlatformNode(parents[i]);
                platformNode.child = this;
                rootPlatformNode = platformNode.getRoot(p);
                if (rootPlatformNode) {
                    this.parent = platformNode;
                    return rootPlatformNode;
                }
            }
        }
        return null;
    };
    PlatformNode.prototype.getSubsetParents = function (subsetPlatformName) {
        var platformRegistry = Platform.registry();
        var parentPlatformNames = [];
        var platform = null;
        for (var platformName in platformRegistry) {
            platform = platformRegistry[platformName];
            if (platform.subsets && platform.subsets.indexOf(subsetPlatformName) > -1) {
                parentPlatformNames.push(platformName);
            }
        }
        return parentPlatformNames;
    };
    return PlatformNode;
}());
var platformRegistry = {};
var platformDefault = null;
function setupPlatform(queryParams, userAgent, navigatorPlatform, dir, lang, zone) {
    registry_1.setupPlatformRegistry();
    var p = new Platform();
    p.setUserAgent(userAgent);
    p.setQueryParams(queryParams);
    p.setNavigatorPlatform(navigatorPlatform);
    p.setDir(dir, false);
    p.setLang(lang, false);
    p.setZone(zone);
    p.load();
    return p;
}
exports.setupPlatform = setupPlatform;
exports.UserAgent = new core_1.OpaqueToken('USERAGENT');
exports.UserNavigatorPlatform = new core_1.OpaqueToken('USERNAVPLT');
exports.UserDir = new core_1.OpaqueToken('USERDIR');
exports.UserLang = new core_1.OpaqueToken('USERLANG');
function providePlatform() {
    return {
        provide: Platform,
        useFactory: setupPlatform,
        deps: [
            query_params_1.QueryParams,
            exports.UserAgent,
            exports.UserNavigatorPlatform,
            exports.UserDir,
            exports.UserLang,
            core_1.NgZone
        ]
    };
}
exports.providePlatform = providePlatform;
