"use strict";
var __extends = (this && this.__extends) || (function () {
    var extendStatics = Object.setPrototypeOf ||
        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
var __assign = (this && this.__assign) || Object.assign || function(t) {
    for (var s, i = 1, n = arguments.length; i < n; i++) {
        s = arguments[i];
        for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
            t[p] = s[p];
    }
    return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
var Config_1 = require("./Config");
var HaikuBase_1 = require("./HaikuBase");
var HaikuClock_1 = require("./HaikuClock");
var HaikuComponent_1 = require("./HaikuComponent");
var pkg = require('./../package.json');
var VERSION = pkg.version;
var HaikuContext = (function (_super) {
    __extends(HaikuContext, _super);
    function HaikuContext(mount, renderer, platform, bytecode, config) {
        var _this = _super.call(this) || this;
        if (!renderer) {
            throw new Error('Context requires a renderer');
        }
        if (!bytecode) {
            throw new Error('Context requires bytecode');
        }
        _this.PLAYER_VERSION = VERSION;
        _this.CORE_VERSION = VERSION;
        _this.assignConfig(config || {}, null);
        _this.mount = mount;
        if (_this.mount && !_this.mount.haiku) {
            _this.mount.haiku = {
                context: _this,
            };
        }
        _this.renderer = renderer;
        if (_this.mount && _this.renderer.initialize) {
            _this.renderer.initialize();
        }
        _this.platform = platform;
        _this.tickables = [];
        _this.tickables.push({ performTick: _this.tick.bind(_this) });
        if (_this.config.frame) {
            _this.tickables.push({ performTick: _this.config.frame });
        }
        _this.clock = new HaikuClock_1.default(_this.tickables, _this.component, _this.config.clock || {});
        _this.clock.run();
        _this.container = _this.renderer.createContainer({
            elementName: bytecode,
            attributes: {},
            children: [bytecode.template],
        });
        _this.component = new HaikuComponent_1.default(bytecode, _this, _this.config, _this.container);
        if (_this.mount && _this.renderer.menuize && _this.config.contextMenu !== 'disabled') {
            _this.renderer.menuize(_this.component);
        }
        if (_this.mount &&
            _this.platform &&
            _this.platform.location &&
            _this.platform.location.hostname !== 'localhost' &&
            _this.platform.location.hostname !== '0.0.0.0') {
            if (_this.renderer.mixpanel && _this.config.mixpanel) {
                _this.renderer.mixpanel(_this.config.mixpanel, _this.component);
            }
        }
        _this.ticks = 0;
        if (_this.config.automount) {
            _this.component.getClock().start();
        }
        return _this;
    }
    HaikuContext.prototype.getRootComponent = function () {
        return this.component;
    };
    HaikuContext.prototype.getClock = function () {
        return this.clock;
    };
    HaikuContext.prototype.contextMount = function () {
        if (this.unmountedTickables) {
            var unmounted = this.unmountedTickables.splice(0);
            for (var i = 0; i < unmounted.length; i++) {
                this.addTickable(unmounted[i]);
            }
        }
    };
    HaikuContext.prototype.contextUnmount = function () {
        this.unmountedTickables = this.tickables.splice(0);
    };
    HaikuContext.prototype.addTickable = function (tickable) {
        var alreadyAdded = false;
        for (var i = 0; i < this.tickables.length; i++) {
            if (tickable === this.tickables[i]) {
                alreadyAdded = true;
                break;
            }
        }
        if (!alreadyAdded) {
            this.tickables.push(tickable);
        }
    };
    HaikuContext.prototype.removeTickable = function (tickable) {
        for (var i = (this.tickables.length - 1); i >= 0; i--) {
            if (tickable === this.tickables[i]) {
                this.tickables.splice(i, 1);
            }
        }
    };
    HaikuContext.prototype.assignConfig = function (config, options) {
        this.config = __assign({}, config);
        if (this.clock) {
            this.clock.assignOptions(this.config.clock);
        }
        if (this.component) {
            if (!options || !options.skipComponentAssign) {
                this.component.assignConfig(this.config);
            }
        }
    };
    HaikuContext.prototype.getContainer = function (doForceRecalc) {
        if (doForceRecalc === void 0) { doForceRecalc = false; }
        if (doForceRecalc || this.renderer.shouldCreateContainer) {
            this.renderer.createContainer(this.container);
        }
        return this.container;
    };
    HaikuContext.prototype.render = function () {
        var tree = this.component.render(this.getContainer(true), this.config);
        if (tree !== undefined) {
            return this.renderer.render(this.getContainer(), tree, this.component);
        }
    };
    HaikuContext.prototype.performFullFlushRender = function () {
        if (!this.mount) {
            return;
        }
        this.render();
    };
    HaikuContext.prototype.performPatchRender = function (skipCache) {
        if (skipCache === void 0) { skipCache = false; }
        if (!this.mount) {
            return;
        }
        var patches = this.component.patch(this.getContainer(), this.config, skipCache);
        this.renderer.patch(patches, this.component);
    };
    HaikuContext.prototype.updateMountRootStyles = function () {
        if (!this.mount) {
            return;
        }
        var root = this.mount && this.mount.children[0];
        if (root) {
            if (this.config.position && root.style.position !== this.config.position) {
                root.style.position = this.config.position;
            }
            if (this.config.overflow) {
                root.style.overflow = this.config.overflow;
            }
            else {
                if (this.config.overflowX &&
                    root.style.overflowX !== this.config.overflowX) {
                    root.style.overflowX = this.config.overflowX;
                }
                if (this.config.overflowY &&
                    root.style.overflowY !== this.config.overflowY) {
                    root.style.overflowY = this.config.overflowY;
                }
            }
        }
    };
    HaikuContext.prototype.tick = function (skipCache) {
        if (skipCache === void 0) { skipCache = false; }
        var flushed = false;
        if (!this.component.isDeactivated() && !this.component.isSleeping()) {
            if (this.component._shouldPerformFullFlush() || this.config.forceFlush || this.ticks < 1) {
                this.performFullFlushRender();
                flushed = true;
            }
            else {
                this.performPatchRender(skipCache);
            }
            this.updateMountRootStyles();
            if (this.ticks < 1) {
                this.component.callRemount(null, flushed);
            }
            this.ticks++;
        }
    };
    HaikuContext.prototype.getGlobalUserState = function () {
        return this.renderer && this.renderer.getUser && this.renderer.getUser();
    };
    return HaikuContext;
}(HaikuBase_1.default));
exports.default = HaikuContext;
HaikuContext['createComponentFactory'] = function (rendererClass, bytecode, haikuConfigFromFactoryCreator, platform) {
    if (!rendererClass) {
        throw new Error('A runtime renderer class object is required');
    }
    if (!bytecode) {
        throw new Error('A runtime `bytecode` object is required');
    }
    var haikuConfigFromTop = Config_1.default.build({
        seed: Config_1.default.seed(),
        timestamp: Date.now(),
    }, bytecode && bytecode.options, haikuConfigFromFactoryCreator);
    var HaikuComponentFactory = function (mount, haikuConfigFromFactory) {
        var haikuConfigMerged = Config_1.default.build(haikuConfigFromTop, haikuConfigFromFactory);
        var renderer = new rendererClass(mount, haikuConfigMerged);
        var context = new HaikuContext(mount, renderer, platform, bytecode, haikuConfigMerged);
        var component = context.getRootComponent();
        HaikuComponentFactory['bytecode'] = bytecode;
        HaikuComponentFactory['renderer'] = renderer;
        HaikuComponentFactory['mount'] = mount;
        HaikuComponentFactory['context'] = context;
        HaikuComponentFactory['component'] = component;
        return component;
    };
    HaikuComponentFactory['PLAYER_VERSION'] = VERSION;
    HaikuComponentFactory['CORE_VERSION'] = VERSION;
    return HaikuComponentFactory;
};
HaikuContext['PLAYER_VERSION'] = VERSION;
HaikuContext['CORE_VERSION'] = VERSION;
//# sourceMappingURL=HaikuContext.js.map