var __assign = (this && this.__assign) || function () {
    __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;
    };
    return __assign.apply(this, arguments);
};
Object.defineProperty(exports, "__esModule", { value: true });
var fs_extra_1 = require("fs-extra");
var path = require("path");
var Logger_1 = require("../Logger");
module.exports = /** @class */ (function () {
    function Page(settings) {
        this.pageFilePath = path.join(Undecked.dataPath, 'pages', "".concat(settings.pageID, ".json"));
        this.pageID = settings.pageID;
        this.name = settings.name || "Unnamed page (".concat(this.pageID, ")");
        this.keys = settings.keys || {};
        this.ensureKeys();
    }
    Page.prototype.save = function (callback) {
        var _this = this;
        clearTimeout(this.saveTimeout);
        this.saveTimeout = setTimeout(function () {
            (0, fs_extra_1.writeJson)(_this.pageFilePath, _this.export(), function (err) {
                if (err)
                    (0, Logger_1.Log)('error', "Error whilst saving page ".concat(_this.pageID), err.message);
                else
                    (0, Logger_1.Log)('info', "Page ".concat(_this.pageID, " has been saved"));
                if (callback)
                    callback();
            });
        }, 10 * 1000);
    };
    Page.prototype.export = function () {
        var keys = JSON.parse(JSON.stringify(this.keys));
        for (var y in keys) {
            for (var x in keys[y]) {
                var key = keys[y][x];
                if (key.state != undefined && key.state.type == 'ghost' && key.state.masterID != undefined) {
                    var location = Undecked.Pages.KeyManager.getLocation(key.state.masterID);
                    var page = Undecked.Pages.get(location.pageID);
                    if (page) {
                        var ghostMaster = page.getKey(location.x, location.y);
                        key.appearence = ghostMaster.appearence;
                        key.actions = ghostMaster.actions;
                    }
                }
            }
        }
        return {
            pageID: this.pageID,
            name: this.name,
            keys: keys
        };
    };
    Page.prototype.getID = function () {
        return this.pageID;
    };
    Page.prototype.ensureKeys = function () {
        for (var y = 0; y < 4; y++) {
            if (this.keys[y] == undefined)
                this.keys[y] = {};
            for (var x = 0; x < 8; x++) {
                if (this.keys[y][x] == undefined)
                    this.keys[y][x] = __assign(__assign({}, defaultKey), { id: null });
                if (this.keys[y][x].id == null || this.keys[y][x].id == undefined)
                    this.keys[y][x].id = Undecked.Pages.KeyManager.generateNew();
                else
                    Undecked.Pages.KeyManager.register(this.keys[y][x].id);
                if (this.keys[y][x].actions == undefined)
                    this.keys[y][x].actions = {};
                if (this.keys[y][x].actions.up == undefined)
                    this.keys[y][x].actions.up = {};
                if (this.keys[y][x].actions.down == undefined)
                    this.keys[y][x].actions.down = {};
                if (this.keys[y][x].actions.latch == undefined)
                    this.keys[y][x].actions.latch = {};
                if (this.keys[y][x].actions.unlatch == undefined)
                    this.keys[y][x].actions.unlatch = {};
                if (this.keys[y][x].state.type == 'ghost') {
                    if (this.keys[y][x].state.masterID != undefined) {
                        var location = Undecked.Pages.KeyManager.getLocation(this.keys[y][x].state.masterID);
                        var page = Undecked.Pages.get(location.pageID);
                        if (page) {
                            var key = page.getKey(location.x, location.y);
                            if (key.state.ghostIDs == undefined)
                                key.state.ghostIDs = [];
                            key.state.ghostIDs.push(this.keys[y][x].id);
                        }
                    }
                }
            }
        }
    };
    Page.prototype.setName = function (name) {
        this.name = name;
        this.save();
        Undecked.SocketServer.broadcastTo('home', 'page', 'updatename', this.pageID, name);
    };
    Page.prototype.broadcastKeyUpdate = function (x, y, responseToken, key) {
        if (responseToken === void 0) { responseToken = '-1'; }
        Undecked.SocketServer.broadcastTo('home', 'page', 'updatekey', this.pageID, x, y, key != undefined ? key : this.keys[y][x], responseToken);
    };
    Page.prototype.updateKey = function (x, y, key, responseToken, originQuery, force) {
        if (force === void 0) { force = false; }
        if (this.keys[y] != undefined && this.keys[y][x] != undefined) {
            //FIXME:GHOST still not working oging to bed now, I think i should rewrite it tomorrow.....
            /* When updating key check if key is a ghost, if so recall the function with the master key. Update all properties on master key as usual. If a key has ghostIDs, update the appearence and actions of the key. */
            //----------------------------------Validating key
            var masterResponseToken = originQuery == undefined
                ? responseToken
                : "".concat(this.pageID, "_").concat(x, "_").concat(y) == originQuery ? responseToken : '-1';
            originQuery = "".concat(this.pageID, "_").concat(x, "_").concat(y);
            var decks = Undecked.Decks.decks;
            var currentKey = this.keys[y][x];
            var grabBest = function (object, value, defaultValue, incommingFirst) {
                if (incommingFirst === void 0) { incommingFirst = true; }
                if (key.state.type == 'empty')
                    return defaultValue;
                if ((incommingFirst == true || force == true) && key[object] != undefined)
                    if (value != null && key[object][value] != undefined)
                        return key[object][value];
                    else if (value == null)
                        return key[object];
                if (currentKey[object] != undefined)
                    if (value != null && currentKey[object][value] != undefined)
                        return currentKey[object][value];
                    else if (value == null)
                        return currentKey[object];
                if (incommingFirst == false && key[object] != undefined)
                    if (value != null && key[object][value] != undefined)
                        return key[object][value];
                    else if (value == null)
                        return key[object];
                return defaultValue;
            };
            if (currentKey.state.type != 'ghost' && key.state.type == 'ghost') {
                //Becoming ghost
            }
            else if (currentKey.state.type == 'ghost' && (key.state.type == 'ghost' || key.state.type == 'custom')) {
                //Editing ghost
                if (key.state.type == 'custom')
                    key.state.type = 'ghost';
                var masterID = currentKey.state.masterID;
                var masterLocation = Undecked.Pages.KeyManager.getLocation(masterID);
                var masterPage = Undecked.Pages.get(masterLocation.pageID);
                if (masterPage) {
                    var masterKeyClone = JSON.parse(JSON.stringify(masterPage.getKey(masterLocation.x, masterLocation.y)));
                    return masterPage.updateKey(masterLocation.x, masterLocation.y, __assign(__assign({}, masterKeyClone), { state: __assign(__assign({}, masterKeyClone.state), { confirm: key.state.confirm, toggle: key.state.toggle }), appearence: key.appearence }), responseToken, originQuery);
                }
                return console.log('Unable to find ghost master key');
            }
            else if (currentKey.state.type == 'ghost' && key.state.type != 'ghost') {
                var masterID = currentKey.state.masterID;
                var masterLocation = Undecked.Pages.KeyManager.getLocation(masterID);
                var masterPage = Undecked.Pages.get(masterLocation.pageID);
                if (masterPage) {
                    var masterKey = masterPage.getKey(masterLocation.x, masterLocation.y);
                    if (masterKey.state != undefined && masterKey.state.ghostIDs != undefined) {
                        if (masterKey.state.ghostIDs.includes(currentKey.id))
                            masterKey.state.ghostIDs.splice(masterKey.state.ghostIDs.indexOf(currentKey.id), 1);
                    }
                }
                //Reverting from ghost
            }
            else if (currentKey.state.type == 'custom' &&
                key.state.type != 'custom' &&
                currentKey.state.ghostIDs != undefined &&
                currentKey.state.ghostIDs.length > 0) {
                //Master becoming other key
                var ghostIDs = currentKey.state.ghostIDs;
                var removeGhost = function (ghostID) {
                    var ghostLocation = Undecked.Pages.KeyManager.getLocation(ghostID);
                    var ghostPage = Undecked.Pages.get(ghostLocation.pageID);
                    if (ghostPage) {
                        var ghostKey = ghostPage.getKey(ghostLocation.x, ghostLocation.y);
                        if (ghostKey.state != undefined && ghostKey.state.masterID == currentKey.id) {
                            if (ghostPage.keys[ghostLocation.y] != undefined &&
                                ghostPage.keys[ghostLocation.y][ghostLocation.x]) {
                                ghostPage.keys[ghostLocation.y][ghostLocation.x] = {
                                    id: ghostKey.id,
                                    appearence: {},
                                    state: { confirm: false, toggle: false, type: 'empty' }
                                };
                                ghostPage.broadcastKeyUpdate(ghostLocation.x, ghostLocation.y);
                            }
                        }
                    }
                };
                for (var i = 0; i < ghostIDs.length; i++) {
                    removeGhost(ghostIDs[i]);
                    continue;
                }
                currentKey.state.ghostIDs = null;
            }
            else {
                //Normal change
            }
            var id = currentKey.id != undefined ? currentKey.id : Undecked.Pages.KeyManager.generateNew();
            var _internal = currentKey._internal != undefined ? currentKey._internal : {};
            var state = {
                confirm: grabBest('state', 'confirm', false),
                toggle: grabBest('state', 'toggle', false),
                type: grabBest('state', 'type', 'empty'),
                masterID: grabBest('state', 'masterID', null, false),
                ghostIDs: grabBest('state', 'ghostIDs', null, false)
            };
            var actions = state.type == 'empty'
                ? { down: {}, up: {}, latch: {}, unlatch: {} }
                : force == true
                    ? key.actions
                    : currentKey.actions != undefined
                        ? currentKey.actions
                        : { up: {}, down: {}, latch: {}, unlatch: {} };
            var appearence = {
                background: grabBest('appearence', 'background', {}),
                image: grabBest('appearence', 'image', {}),
                text: grabBest('appearence', 'text', {})
            };
            this.keys[y][x] = {
                id: id,
                _internal: _internal,
                actions: actions,
                state: state,
                appearence: appearence
            };
            //----------------------------------Updating decks & web ui
            var deckPages = {};
            for (var serialNumber in decks) {
                var deck = decks[serialNumber];
                if (deckPages[deck.getPageID()] == undefined)
                    deckPages[deck.getPageID()] = [];
                deckPages[deck.getPageID()].push(deck);
                if (deck.getPageID() == this.pageID) {
                    deck.updateKey(parseInt(x), parseInt(y));
                }
            }
            if (this.keys[y][x].state.type == 'ghost') {
                var masterLocation = Undecked.Pages.KeyManager.getLocation(this.keys[y][x].state.masterID);
                var masterPage = Undecked.Pages.get(masterLocation.pageID);
                if (masterPage) {
                    var masterClone = JSON.parse(JSON.stringify(masterPage.getKey(masterLocation.x, masterLocation.y)));
                    this.broadcastKeyUpdate(x, y, masterResponseToken, __assign(__assign({}, key), { state: __assign(__assign({}, key.state), { confirm: masterClone.state.confirm, toggle: masterClone.state.toggle }), appearence: masterClone.appearence }));
                }
            }
            else
                this.broadcastKeyUpdate(x, y, masterResponseToken);
            if (currentKey.state.type == 'custom' &&
                currentKey.state.ghostIDs != undefined &&
                currentKey.state.ghostIDs.length > 0) {
                //Updating ghost of this key
                var ghostAppearence = JSON.parse(JSON.stringify(appearence));
                ghostAppearence.system = { ghost: true };
                for (var i = 0; i < currentKey.state.ghostIDs.length; i++) {
                    var ghostID = currentKey.state.ghostIDs[i];
                    var ghostLocation = Undecked.Pages.KeyManager.getLocation(ghostID);
                    var ghostPage = Undecked.Pages.get(ghostLocation.pageID);
                    if (ghostPage) {
                        var ghostKeyClone = JSON.parse(JSON.stringify(ghostPage.getKey(ghostLocation.x, ghostLocation.y)));
                        if (ghostKeyClone.state != undefined && ghostKeyClone.state.masterID == id) {
                            var responseTokenGhost = originQuery == undefined
                                ? responseToken
                                : "".concat(ghostLocation.pageID, "_").concat(ghostLocation.x, "_").concat(ghostLocation.y) == originQuery
                                    ? responseToken
                                    : '-1';
                            var newGhostKey = __assign(__assign({}, ghostKeyClone), { appearence: ghostAppearence });
                            ghostPage.broadcastKeyUpdate(ghostLocation.x, ghostLocation.y, responseTokenGhost, newGhostKey);
                            if (deckPages[ghostPage.getID()] != undefined)
                                for (var i_1 = 0; i_1 < deckPages[ghostPage.getID()].length; i_1++) {
                                    var deck = deckPages[ghostPage.getID()][i_1];
                                    deck.setKey(ghostLocation.x, ghostLocation.y, newGhostKey);
                                }
                        }
                        else {
                            currentKey.state.ghostIDs.splice(i, 1);
                            i--;
                        }
                    }
                }
            }
            this.save();
        }
    };
    Page.prototype.setKeyInternal = function (x, y, property, value) {
        if (this.keys[y] != undefined && this.keys[y][x] != undefined) {
            this.keys[y][x]._internal[property] = value;
            this.save();
        }
    };
    Page.prototype.getKey = function (x, y) {
        if (this.keys[y] != undefined && this.keys[y][x] != undefined)
            return this.keys[y][x];
        return null;
    };
    Page.prototype.requestKey = function (x, y) {
        if (this.keys[y] != undefined && this.keys[y][x] != undefined) {
            if (this.keys[y][x].state != undefined &&
                this.keys[y][x].state.type == 'ghost' &&
                this.keys[y][x].state.masterID != undefined) {
                var key = JSON.parse(JSON.stringify(this.keys[y][x]));
                var location = Undecked.Pages.KeyManager.getLocation(key.state.masterID);
                var page = Undecked.Pages.get(location.pageID);
                if (page) {
                    var ghostMasterClone = JSON.parse(JSON.stringify(page.getKey(location.x, location.y)));
                    key.state = __assign(__assign({}, this.keys[y][x].state), { confirm: ghostMasterClone.state.confirm, toggle: ghostMasterClone.state.toggle });
                    key.appearence = ghostMasterClone.appearence;
                    key.actions = ghostMasterClone.actions;
                    return key;
                }
            }
            else
                return this.keys[y][x];
        }
        return null;
    };
    Page.prototype.hasKey = function (x, y) {
        return this.keys[y] != undefined && this.keys[y][x] != undefined;
    };
    Page.prototype.hasKeyWithID = function (keyID) {
        for (var y = 0; y < 4; y++)
            for (var x = 0; x < 8; x++)
                if (this.keys[y] != undefined && this.keys[y][x] != undefined)
                    if (this.keys[y][x].id == keyID)
                        return true;
        return false;
    };
    Page.prototype.getKeyLocationWithID = function (keyID) {
        for (var y = 0; y < 4; y++)
            for (var x = 0; x < 8; x++)
                if (this.keys[y] != undefined && this.keys[y][x] != undefined)
                    if (this.keys[y][x].id == keyID)
                        return { x: x, y: y };
        return null;
    };
    Page.prototype.getKeyTextList = function () {
        var list = [];
        for (var y = 0; y < 4; y++)
            for (var x = 0; x < 8; x++) {
                if (this.keys[y] != undefined && this.keys[y][x] != undefined) {
                    var key = this.keys[y][x];
                    if (key.appearence != undefined && key.appearence.text != undefined) {
                        if (key.appearence.text.value != undefined && key.appearence.text.value.length > 0) {
                            list.push({ x: x, y: y, text: key.appearence.text.value, id: key.id });
                            continue;
                        }
                    }
                    list.push({ x: x, y: y, text: null, id: key.id });
                }
                else
                    list.push({ x: x, y: y, text: null, id: null });
            }
        return list;
    };
    Page.prototype.getActionInstance = function (key, actionInstanceID) {
        if (key.actions != undefined) {
            if (key.actions.up != undefined && key.actions.up[actionInstanceID] != undefined)
                return key.actions.up[actionInstanceID];
            if (key.actions.down != undefined && key.actions.down[actionInstanceID] != undefined)
                return key.actions.down[actionInstanceID];
            if (key.actions.latch != undefined && key.actions.latch[actionInstanceID] != undefined)
                return key.actions.latch[actionInstanceID];
            if (key.actions.unlatch != undefined && key.actions.unlatch[actionInstanceID] != undefined)
                return key.actions.unlatch[actionInstanceID];
        }
        return null;
    };
    return Page;
}());
var defaultKey = {
    id: null,
    state: {
        type: 'empty',
        toggle: false,
        confirm: false
    },
    actions: {
        up: {},
        down: {},
        latch: {},
        unlatch: {}
    },
    appearence: {
        text: {
            color: '#ffffff',
            size: 20,
            value: '',
            offsetX: 0,
            offsetY: 0
        }
    },
    _internal: {}
};
//# sourceMappingURL=Page.js.map