const util = require('util');
const EventEmitter = require('events').EventEmitter;
const types = require('../web-server/event-types');
const playerEventsToPush = class playerEventsToPush {
    constructor({
                    push,
                    config,
                    utils,
                    schedulePlayer,
                    announcePlayer,
                    djPlayer,
                    pushAudioPlayer,
                    icePlayer,
                    thirdPartyPlayer,
                    announcesDownloader,
                    schedulesDownloader,
                    streamPlayer,
                    bluetooth,
                    moment
                } = {}) {
        this.push = push;
        this.config = config;
        this.utils = utils;
        this.schedulePlayer = schedulePlayer;
        this.announcePlayer = announcePlayer;
        this.djPlayer = djPlayer;
        this.pushAudioPlayer = pushAudioPlayer;
        this.icePlayer = icePlayer;
        this.thirdPartyPlayer = thirdPartyPlayer;
        this.announcesDownloader = announcesDownloader;
        this.schedulesDownloader = schedulesDownloader;
        this.streamPlayer = streamPlayer;
        this.bluetooth = bluetooth;
        this.moment = moment;
        this.users = [];
        this.channelName = '';
        this.serialNumber = this.utils.serial;
        this.lastEmitSchedulesVumeter = this.moment().utc(true);
        this.lastEmitAnnouncesVumeter = this.moment().utc(true);
        this.lastEmitThirdPartyVumeter = this.moment().utc(true);
        this.lastEmitStreamVumeter = this.moment().utc(true);
        this.lastEmitDjVumeter = this.moment().utc(true);
        this.prepareEvents();
    }

    clearUsers() {
        delete this.users;
        this.users = {};
    }

    addUser(user) {

        if (typeof this.users[user] == 'undefined') {
            this.users[user] = user;
        }
    }

    removeUser(user) {
        if (typeof this.users[user] == 'string') {
            delete this.users[user];
        }
    }

    setMyId(uid) {
        this.myid = uid;
    }

    setChannel(channelName) {
        this.channelName = channelName;
    }

    async EmitToClients(data) {
        //todo: re-enable when we implement remote vumeter
        return;
        let vumeterDelay=0.3
        let now = this.moment().utc(true);
        if(data.eventName == 'schedules/vumeterChanged') {
            if(now.diff(this.lastEmitSchedulesVumeter, 'seconds') <= vumeterDelay) {
                return;
            } else {
                this.lastEmitSchedulesVumeter = now;
            }
        }
        if(data.eventName == 'announces/vumeterChanged') {
            if(now.diff(this.lastEmitAnnouncesVumeter, 'seconds') <= vumeterDelay) {
                return;
            } else {
                this.lastEmitAnnouncesVumeter = now;
            }
        }

        if(data.eventName == 'djPlayer/vumeterChanged') {
            if(now.diff(this.lastEmitDjVumeter, 'seconds') <= vumeterDelay) {
                return;
            } else {
                this.lastEmitDjVumeter = now;
            }
        }

        if(data.eventName == 'streaming/vumeterChanged') {
            if(now.diff(this.lastEmitStreamVumeter, 'seconds') <= vumeterDelay) {
                return;
            } else {
                this.lastEmitStreamVumeter = now;
            }
        }
        if (Object.keys(this.users).length > 1) {
            let result = await this.push.PublishMsg(this.channelName, JSON.stringify(data), this.push._pushFunctions.ClientSendsPlayerEvents);
            if (result.sended == false) {
                console.log('unable to publish playerEvent to channel:', result.msg)
            }
        }
    }

    sendInit(){
        //types.initialize,
          var obj=  {
            config: {
                version: this.version,
                hasBluetooth: this.bluetooth.isBluetoothControlExists,
                hasDj: this.config.DJ.DJEnabled,
                hasSchedulesNextButton: this.config.Settings.NextButtonVisible,
                bluetoothAutoConnectMac: this.config.Bluetooth.macID
            },
            schedules: {
                currentSongIndex: this.schedulePlayer.currentSong.FilePosition,
                currentSong: {
                    originalName: this.schedulePlayer.currentSong.OriginalName,
                    fileName: this.schedulePlayer.currentSong.FileName
                },
                songCount: this.schedulePlayer.currentSong.TotalFiles,
                duration: this.schedulePlayer.currentSong.Duration,
                position: this.schedulePlayer.currentSong.Position,
                vumeter: {
                    left: this.schedulePlayer.currentSong.vumeterLeft,
                    right: this.schedulePlayer.currentSong.vumeterRight
                }
            },
            connected: true
        };
        this.EmitToClients({
            eventName: `${types.initialize}`,
            data: obj
        });
    }

    async prepareEvents() {
        //this.prepareBluetoothEvents();
        this.prepareSchedulesDownloaderEvents();
        this.prepareAnnouncesDownloaderEvents();
        this.preparePushAudioEvents();
        this.prepareDjPlayerEvents();
        this.prepareAnnouncePlayerEvents();
        this.prepareSchedulePlayerEvents();
        this.prepareStreamPlayerEvents();
    }

    prepareBluetoothEvents() {

        this.bluetooth.on(this.bluetooth.bluetoothEvents.Controller, (controllers) => {
            this.EmitToClients({
                    eventName: `${types.bluetooth.namespace}/${types.bluetooth.events.controllers}`,
                    data: {controllers: controllers}
                }
            )
        });

        this.bluetooth.on(this.bluetooth.bluetoothEvents.Device, (devices) => {
            this.EmitToClients({
                eventName: `${types.bluetooth.namespace}/${types.bluetooth.events.devices}`,
                data: {devices: devices}
            })

        });
    }

    prepareSchedulesDownloaderEvents() {
        this.schedulesDownloader.on(this.schedulesDownloader.eventTypes.onProgress, (filename, percentage, currentStr, durationStr, speed, current, length) => {
            this.EmitToClients({
                eventName: `${types.downloads.namespace}/${types.downloads.events.schedulesProgress}`,
                data: {
                    filename: filename,
                    percentage: percentage,
                    currentStr: currentStr,
                    durationStr: durationStr,
                    speed: speed
                }
            });
        });
        this.schedulesDownloader.on(this.schedulesDownloader.eventTypes.onDownloadCompleted, (pageStatus, pageMessage, filename) => {
            this.EmitToClients({
                eventName: `${types.downloads.namespace}/${types.downloads.events.schedulesCompleted}`,
                data: {
                    pageStatus: pageStatus, pageMessage: pageMessage, filename: filename
                }
            });
        });
        this.schedulesDownloader.on(this.schedulesDownloader.eventTypes.onError, (file) => {
            this.EmitToClients({
                eventName: `${types.downloads.namespace}/${types.downloads.events.schedulesError}`,
                data: {
                    file: file
                }
            });
        });
        this.schedulesDownloader.on(this.schedulesDownloader.eventTypes.onListCompleted, () => {
            this.EmitToClients({
                eventName: `${types.downloads.namespace}/${types.downloads.events.schedulesListCompleted}`,
                data: {}
            });
        });
    }

    prepareAnnouncesDownloaderEvents() {
        this.announcesDownloader.on(this.announcesDownloader.eventTypes.onProgress, (filename, percentage, currentStr, durationStr, speed, current, length) => {
            this.EmitToClients({
                eventName: `${types.downloads.namespace}/${types.downloads.events.announcesProgress}`,
                data: {
                    filename: filename,
                    percentage: percentage,
                    currentStr: currentStr,
                    durationStr: durationStr,
                    speed: speed
                }
            });
        });
        this.announcesDownloader.on(this.announcesDownloader.eventTypes.onDownloadCompleted, (pageStatus, pageMessage, filename) => {
            this.EmitToClients({
                eventName: `${types.downloads.namespace}/${types.downloads.events.announcesCompleted}`,
                data: {
                    pageStatus: pageStatus, pageMessage: pageMessage, filename: filename
                }
            });
        });
        this.announcesDownloader.on(this.announcesDownloader.eventTypes.onError, (file) => {
            this.EmitToClients({
                eventName: `${types.downloads.namespace}/${types.downloads.events.announcesError}`,
                data: {
                    file: file
                }
            });
        });
        this.announcesDownloader.on(this.announcesDownloader.eventTypes.onListCompleted, () => {
            this.EmitToClients({
                eventName: `${types.downloads.namespace}/${types.downloads.events.announcesListCompleted}`,
                data: {}
            });
        });
    }

    preparePushAudioEvents() {
        this.pushAudioPlayer.on(this.pushAudioPlayer.pushAudioEvents.pushAudioStarted, () => {
            this.EmitToClients({
                eventName: `${types.pushaudio.namespace}/${types.pushaudio.events.started}`,
                data: {}
            });
        });

        this.pushAudioPlayer.on(this.pushAudioPlayer.pushAudioEvents.pushAudioStopped, () => {
            this.EmitToClients({
                eventName: `${types.pushaudio.namespace}/${types.pushaudio.events.stopped}`,
                data: {}
            });
        });
    }

    prepareDjPlayerEvents() {
        this.djPlayer.on(this.djPlayer.eventTypes.fileChanged, (chan, FileName, activeFile, duration, index) => {
            this.EmitToClients({
                eventName: `${types.djPlayer.namespace}/${types.djPlayer.events.songChanged}`,
                data: {FileName: FileName, activeFile: activeFile, duration: duration, index: index}
            });
        });
        this.djPlayer.on(this.djPlayer.eventTypes.playlistFinished, () => {
            this.EmitToClients({
                eventName: `${types.djPlayer.namespace}/${types.djPlayer.events.playListFinished}`,
                data: {}
            });
        });
        this.djPlayer.on(this.djPlayer.eventTypes.positionChange, (activeFile, pos, dur, position, duration) => {
            this.EmitToClients({
                eventName: `${types.djPlayer.namespace}/${types.djPlayer.events.positionChange}`,
                data: {activeFile: activeFile, pos: pos, dur: dur, position: position, duration: duration}
            });
        });
        this.djPlayer.on(this.djPlayer.eventTypes.stateChanged, (state) => {
            this.EmitToClients({
                eventName: `${types.djPlayer.namespace}/${types.djPlayer.events.stateChange}`,
                data: {state: state}
            });
        });
        this.djPlayer.on(this.djPlayer.eventTypes.vumeter, (left, right) => {
            this.EmitToClients({
                eventName: `${types.djPlayer.namespace}/${types.djPlayer.events.vumeterChanged}`,
                data: {left: left, right: right}
            });
        });
        this.djPlayer.on(this.djPlayer.eventTypes.djPlayerStarted, () => {
            this.EmitToClients({
                eventName: `${types.djPlayer.namespace}/${types.djPlayer.events.started}`,
                data: {}
            });
        });

        this.djPlayer.on(this.djPlayer.eventTypes.djPlayerStopped, () => {
            this.EmitToClients({
                eventName: `${types.djPlayer.namespace}/${types.djPlayer.events.stopped}`,
                data: {}
            });
        });
    }

    prepareAnnouncePlayerEvents() {
        this.announcePlayer.on(this.announcePlayer.eventTypes.fileChanged, (chan, FileName, activeFile, duration, index) => {


            this.EmitToClients({
                eventName: `${types.announces.namespace}/${types.announces.events.songChanged}`,
                data: {FileName: FileName, activeFile: activeFile, duration: duration, index: index,totalFiles:this.announcePlayer.nowPlaying.TotalFiles,filePosition:this.announcePlayer.nowPlaying.FilePosition}
            });
        });
        this.announcePlayer.on(this.announcePlayer.eventTypes.playlistFinished, () => {
            this.EmitToClients({
                eventName: `${types.announces.namespace}/${types.announces.events.announceFinished}`,
                data: {}
            });
        });
        this.announcePlayer.on(this.announcePlayer.eventTypes.positionChange, (activeFile, pos, dur, position, duration) => {
            this.EmitToClients({
                eventName: `${types.announces.namespace}/${types.announces.events.positionChanged}`,
                data: {activeFile: activeFile, pos: pos, dur: dur, position: position, duration: duration}
            });
        });

        this.announcePlayer.on(this.announcePlayer.eventTypes.vumeter, (left, right) => {
            this.EmitToClients({
                eventName: `${types.announces.namespace}/${types.announces.events.vumeterChanged}`,
                data: {left: left, right: right}
            });
        });
        this.announcePlayer.on(this.announcePlayer.eventTypes.announcesStarted, () => {
            this.EmitToClients({
                eventName: `${types.announces.namespace}/${types.announces.events.announceStarted}`,
                data: {}
            });
        });
        this.announcePlayer.on(this.announcePlayer.eventTypes.announcesFinished, () => {
            this.EmitToClients({
                eventName: `${types.announces.namespace}/${types.announces.events.announceFinished}`,
                data: {}
            });
        });

    }

    prepareSchedulePlayerEvents() {
        this.schedulePlayer.on(this.schedulePlayer.eventTypes.fileChanged, (chan, FileName, activeFile, duration, index) => {
            this.EmitToClients({
                eventName: `${types.schedules.namespace}/${types.schedules.events.songChanged}`,
                data: {FileName: FileName, activeFile: activeFile, duration: duration, index: index}
            });
        });
        this.schedulePlayer.on(this.schedulePlayer.eventTypes.playlistFinished, () => {
            this.EmitToClients({
                eventName: `${types.schedules.namespace}/${types.schedules.events.playListFinished}`,
                data: {}
            });
        });
        this.schedulePlayer.on(this.schedulePlayer.eventTypes.positionChange, (activeFile, pos, dur, position, duration) => {
            this.EmitToClients({
                eventName: `${types.schedules.namespace}/${types.schedules.events.positionChanged}`,
                data: {activeFile: activeFile, pos: pos, dur: dur, position: position, duration: duration}
            });
        });
        this.schedulePlayer.on(this.schedulePlayer.eventTypes.stateChanged, (state) => {
            this.EmitToClients({
                eventName: `${types.schedules.namespace}/${types.schedules.events.stateChange}`,
                data: {state: state}
            });
        });
        this.schedulePlayer.on(this.schedulePlayer.eventTypes.vumeter, (left, right) => {
            this.EmitToClients({
                eventName: `${types.schedules.namespace}/${types.schedules.events.vumeterChanged}`,
                data: {left: left, right: right}
            });
        });

    }

    prepareStreamPlayerEvents() {
        this.streamPlayer.on(this.streamPlayer.streamEvents.vumeter, (left, right) => {
            this.EmitToClients({
                eventName: `${types.streaming.namespace}/${types.streaming.events.vumeter}`,
                data: {left: left, right: right}
            });
        });

        this.streamPlayer.on(this.streamPlayer.streamEvents.fileChanged, () => {
            this.EmitToClients({
                eventName: `${types.streaming.namespace}/${types.streaming.events.fileChanged}`,
                data: {}
            });
        });
        this.streamPlayer.on(this.streamPlayer.streamEvents.positionChange, (pos, dur, chan) => {
            this.EmitToClients({
                eventName: `${types.streaming.namespace}/${types.streaming.events.positionChange}`,
                data: {pos: pos, dur: dur}
            });
        });
        this.streamPlayer.on(this.streamPlayer.streamEvents.stateChanged, (state) => {
            this.EmitToClients({
                eventName: `${types.streaming.namespace}/${types.streaming.events.stateChanged}`,
                data: {state: state}
            });
        });
        this.streamPlayer.on(this.streamPlayer.streamEvents.urlChanged, (url) => {
            this.EmitToClients({
                eventName: `${types.streaming.namespace}/${types.streaming.events.urlChange}`,
                data: {url: url}
            });
        });
        this.streamPlayer.on(this.streamPlayer.streamEvents.streamPlayerError, (err) => {
            this.EmitToClients({
                eventName: `${types.streaming.namespace}/${types.streaming.events.status}`,
                data: {status: err}
            });
        });

        this.streamPlayer.on(this.streamPlayer.streamEvents.streamPlayerStarted, () => {
            this.EmitToClients({
                eventName: `${types.streaming.namespace}/${types.streaming.events.started}`,
                data: {}
            });
        });

        this.streamPlayer.on(this.streamPlayer.streamEvents.streamPlayerStopped, () => {
            this.EmitToClients({
                eventName: `${types.streaming.namespace}/${types.streaming.events.stopped}`,
                data: {}
            });
        });
    }
};

util.inherits(playerEventsToPush, EventEmitter);
module.exports = playerEventsToPush;
