"use strict";
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 HaikuClock_1 = require("./HaikuClock");
var HaikuComponent_1 = require("./HaikuComponent");
var HaikuGlobal_1 = require("./HaikuGlobal");
var PRNG_1 = require("./helpers/PRNG");
var pkg = require('./../package.json');
var VERSION = pkg.version;
var DEFAULT_TIMELINE_NAME = 'Default';
var HaikuContext = (function () {
    function HaikuContext(mount, renderer, platform, bytecode, config) {
        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._prng = null;
        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._mount);
        }
        this._platform = platform;
        this._entityIndex = HaikuContext['contexts'].push(this) - 1;
        this._tickables = [];
        this._tickables.push({ performTick: this.tick.bind(this) });
        if (this.config.options.frame) {
            this._tickables.push({ performTick: this.config.options.frame });
        }
        this.component = new HaikuComponent_1.default(bytecode, this, this.config, null);
        this.clock = new HaikuClock_1.default(this._tickables, this.component, this.config.options.clock || {});
        this.clock.run();
        this.component.startTimeline(DEFAULT_TIMELINE_NAME);
        if (this._mount && this._renderer.menuize && this.config.options.contextMenu !== 'disabled') {
            this._renderer.menuize(this._mount, 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.options.mixpanel) {
                this._renderer.mixpanel(this.config.options.mixpanel, this.component);
            }
        }
        this._ticks = 0;
        if (this.config.options.automount) {
            this.component.getClock().start();
        }
    }
    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.options.clock);
        }
        if (this.component) {
            if (!options || !options.skipComponentAssign) {
                this.component.assignConfig(this.config);
            }
        }
        this._prng = new PRNG_1.default(this.config.options.seed);
    };
    HaikuContext.prototype.render = function () {
        var container = this._renderer.createContainer(this._mount);
        var tree = this.component.render(container, this.config.options);
        if (tree !== undefined) {
            return this._renderer.render(this._mount, container, 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 container = this._renderer.shouldCreateContainer
            ? this._renderer.createContainer(this._mount)
            : this._renderer.getLastContainer();
        var patches = this.component.patch(container, this.config.options, skipCache);
        this._renderer.patch(this._mount, patches, this.component);
    };
    HaikuContext.prototype.updateMountRootStyles = function () {
        if (!this._mount) {
            return;
        }
        var root = this._mount && this._mount.children[0];
        if (root) {
            if (this.config.options.position && root.style.position !== this.config.options.position) {
                root.style.position = this.config.options.position;
            }
            if (this.config.options.overflow) {
                root.style.overflow = this.config.options.overflow;
            }
            else {
                if (this.config.options.overflowX &&
                    root.style.overflowX !== this.config.options.overflowX) {
                    root.style.overflowX = this.config.options.overflowX;
                }
                if (this.config.options.overflowY &&
                    root.style.overflowY !== this.config.options.overflowY) {
                    root.style.overflowY = this.config.options.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.options.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.getDeterministicRand = function () {
        return this._prng.random();
    };
    HaikuContext.prototype.getDeterministicTime = function () {
        var runningTime = this.getClock().getRunningTime();
        var seededTime = this.config.options.timestamp;
        return seededTime + runningTime;
    };
    HaikuContext.prototype.getGlobalUserState = function () {
        return this._renderer && this._renderer.getUser && this._renderer.getUser();
    };
    return HaikuContext;
}());
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({
        options: {
            seed: Config_1.default.seed(),
            timestamp: Date.now(),
        },
    }, {
        options: bytecode && bytecode.options,
    }, haikuConfigFromFactoryCreator);
    var HaikuComponentFactory = function (mount, haikuConfigFromFactory) {
        var haikuConfigMerged = Config_1.default.build(haikuConfigFromTop, haikuConfigFromFactory);
        var renderer = new rendererClass(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['contexts'] = [];
HaikuContext['PLAYER_VERSION'] = VERSION;
HaikuContext['CORE_VERSION'] = VERSION;
HaikuGlobal_1.default['HaikuContext'] = HaikuContext;
//# sourceMappingURL=HaikuContext.js.map