"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AtemKeySync = void 0;
const events_1 = require("events");
const DeviceManager_1 = require("./devices/DeviceManager");
const ConfigManager_1 = require("./ConfigManager");
const shortid = require("shortid");
const LogTypes_1 = require("../common/LogTypes");
class AtemKeySync extends events_1.EventEmitter {
    constructor(devices, config, logger) {
        super();
        this.settings = [];
        this.devices = devices;
        this.config = config;
        this.logger = logger;
        this.config.on(ConfigManager_1.ConfigManager.Events.Loaded, () => this.onConfigLoaded());
        if (config.isLoaded()) {
            this.onConfigLoaded();
        }
        this.devices.on(DeviceManager_1.DeviceManager.Events.DevicesChanged, () => this.registerAllToDevices());
    }
    setSetting(setting) {
        this.applySetting(setting);
        this.config.updateConfigSection(ConfigManager_1.ConfigSections.AtemKeySync, this.settings.map(s => s.config));
        this.emit(AtemKeySync.Events.SettingsChanged);
    }
    deleteSetting(id) {
        if (!id)
            return;
        const setting = this.settings.find(s => s.config.id === id);
        if (setting) {
            const index = this.settings.indexOf(setting);
            if (index >= 0) {
                this.settings.splice(index, 1);
                if (setting.sourceDevice && setting.handler) {
                    setting.sourceDevice.removeListener('stateChanged', setting.handler);
                }
                this.config.updateConfigSection(ConfigManager_1.ConfigSections.AtemKeySync, this.settings.map(s => s.config));
                this.emit(AtemKeySync.Events.SettingsChanged);
            }
        }
    }
    getSettings() {
        return this.settings.map(s => s.config);
    }
    getKeyPath(keyId) {
        if (!keyId)
            return [];
        if (keyId.startsWith('dsk')) {
            const dskId = parseInt(keyId.substr(3), 10) - 1;
            return [`video.downstreamKeyers.${dskId}`];
        }
        else if (keyId.startsWith('me')) {
            const keyIdParts = keyId.split('_');
            if (keyIdParts.length === 2) {
                const meId = parseInt(keyIdParts[0].substr(2, 1), 10);
                const uskId = parseInt(keyIdParts[1].substr(3), 10);
                return [
                    `video.ME.${meId}.upstreamKeyers.${uskId}.onAir`,
                    `video.ME.${meId}.transition`
                ];
            }
        }
        return [];
    }
    applySetting(setting) {
        if (!setting || !setting.source || !setting.destinations)
            return;
        if (!setting.id)
            setting.id = shortid.generate();
        setting.source.id = setting.source.deviceId + '_' + setting.source.keyId;
        for (const destination of setting.destinations) {
            destination.id = destination.deviceId + '_' + destination.keyId;
        }
        let stored = this.settings.find(s => s.config.id === setting.id);
        if (stored) {
            stored.config = { ...setting };
            stored.sourceKeyPaths = this.getKeyPath(setting.source.keyId);
        }
        else {
            stored = {
                config: { ...setting },
                sourceKeyPaths: this.getKeyPath(setting.source.keyId),
                sourceOnAir: false,
                sourceInTransition: false
            };
            this.settings.push(stored);
        }
        this.registerToDevice(stored);
    }
    onConfigLoaded() {
        const settings = this.config.getConfigSection(ConfigManager_1.ConfigSections.AtemKeySync);
        this.settings.splice(0, this.settings.length);
        for (const setting of settings) {
            this.applySetting(setting);
        }
        this.emit(AtemKeySync.Events.SettingsChanged);
        if (this.settings.length > 0) {
            this.logger.log('Keyer Sync settings loaded', LogTypes_1.LogLevel.Info, { type: 'KEYSYNC', id: '' });
        }
    }
    registerAllToDevices() {
        for (const setting of this.settings) {
            this.registerToDevice(setting);
        }
    }
    registerToDevice(setting) {
        if (!setting || !setting.config || !setting.config.source)
            return;
        if (setting.sourceDevice && setting.handler) {
            setting.sourceDevice.removeListener('stateChanged', setting.handler);
        }
        setting.sourceOnAir = false;
        setting.sourceInTransition = false;
        setting.sourceDevice = this.devices.getDevice(setting.config.source.deviceId);
        if (setting.sourceDevice && setting.sourceDevice.getType() === 'ATEM') {
            const handler = (_state, paths) => {
                for (const path of paths) {
                    for (const testPath of setting.sourceKeyPaths) {
                        if (path.startsWith(testPath)) {
                            if (!setting.sourceDevice) {
                                setting.sourceDevice = this.devices.getDevice(setting.config.source.deviceId);
                            }
                            const keyState = setting.sourceDevice?.getKeyerState(setting.config.source.keyId);
                            // Only handle changes
                            if (keyState && (keyState.onAir !== setting.sourceOnAir || (keyState.inTransition && !setting.sourceInTransition))) {
                                let onAir = false;
                                if (keyState.inTransition) {
                                    onAir = !setting.sourceOnAir;
                                }
                                else {
                                    onAir = keyState.onAir;
                                }
                                const desiredKeyState = {
                                    onAir,
                                    inTransition: keyState.inTransition
                                };
                                for (const destination of setting.config.destinations) {
                                    const destinationDevice = this.devices.getDevice(destination.deviceId);
                                    if (destinationDevice && destinationDevice.getType() === 'ATEM') {
                                        destinationDevice.setKeyerState(destination.keyId, desiredKeyState);
                                    }
                                }
                                setting.sourceOnAir = keyState.onAir;
                                this.logger.log(`Handled keyer sync event "${path}"`, LogTypes_1.LogLevel.Info, { type: 'KEYSYNC', id: '' });
                            }
                            if (keyState !== undefined) {
                                setting.sourceInTransition = keyState.inTransition;
                            }
                            console.log(setting);
                        }
                    }
                }
            };
            setting.sourceDevice.on('stateChanged', handler);
            setting.handler = handler;
            // execute handler on first assigment
            handler(undefined, setting.sourceKeyPaths);
            setting.sourceDevice.on('connected', () => {
                // execute handler on first connection
                handler(undefined, setting.sourceKeyPaths);
            });
        }
    }
}
exports.AtemKeySync = AtemKeySync;
AtemKeySync.Events = {
    SettingsChanged: 'changed'
};
//# sourceMappingURL=AtemKeySync.js.map