//register websync module
const util = require('util');
require('linqjs');
require('./fm.js');
require('./fm.websync.js');
require('./fm.websync.subscribers');
fm.xhr.setDisableBinary(true);

const xreq = require('./XmlHttpRequest');
window.XMLHttpRequest = xreq.XMLHttpRequest;


const clsLogger = require('../logs/clsLogger').clsLogger;
const logger = new clsLogger();
const Encryptor = require('../Encrypter/Encrypt');
const enc = new Encryptor();
const Compressor = require('../compressor/compressor');
const compressor = new Compressor();
const moment = require('moment');


class SMGPush {
    constructor({connectionUrl, retryConnect, db, schedulesdb, announcesdb, utils, config, logdb, playerEventsToPush} = {}) {
        this.logdb = logdb;
        this.db = db;
        this.config = config;
        this.schedulesdb = schedulesdb;
        this.announcesdb = announcesdb;
        this.utils = utils;
        this.playerEventsToPush = playerEventsToPush;
        //<editor-fold desc="definitions">
        this.connectionStatusMessages = {
            Connected: 'Connected',
            Failure: 'Failure',
            Retrying: 'Retrying Connection',
            Disconnected: 'Disconnected'
        };
        this.eventsTypes = {
            ServerRequestsScheduleLastUpdateDate: 'ServerRequestsScheduleLastUpdateDate',
            ThereIsScheduleChangeOnServer: 'ThereIsScheduleChangeOnServer',
            ServerRequestsAnnouncesLastUpdateDate: 'ServerRequestsAnnouncesLastUpdateDate',
            ThereIsAnnounceChangeOnServer: 'ThereIsAnnounceChangeOnServer',
            ServerRequestsStreamUrlChange: 'ServerRequestsStreamUrlChange',
            ConnectionStatus: 'ConnectionStatus',
            AppUpdateReceived: 'AppUpdateReceived',
            PushAudioReceived: 'PushAudioReceived',
            NotifyEvent: 'NotifyEvent',
            ThirdPartyApiKeys: 'ThirdPartyApiKeys'
        };
        this._proxyOptions = {
            user: config.proxy.proxyUser,
            pass: config.proxy.proxyPass,
            port: config.proxy.proxyPort,
            host: config.proxy.proxyHost,
            enabled: config.proxy.proxyEnabled == 1 ? true : false
        };

        this.UserType = {
            Windows: 1,
            Linux: 2,
            LinuxConsole: 3,
            WindowsService: 4,
            Silverlight: 5,
            Javascript: 6,
            MacOSX: 7,
            default: 8
        };

        this.PlayerSpecificActions={
            PlayNext:1,
            DJPlayerPlay:2,
            DJPlayerStop:3,
            DJPlayerGetList:4,
            Restart:5

        };

        //register enum module
        this._pushFunctions = {
            Users: 1,
            user: 2,
            Text: 3,
            ServerRequestsLastUpdateDate: 4,
            ThereIsChangeOnServerForU: 5,
            ClientSendsLastUpdateDate: 6,
            ClientRequestsSchedulesForDevice: 7,
            ServerSendsSchedules: 8,
            ServerRequestsAnnouncesLastUpdateDate: 9,
            ClientSendsAnnouncesLastUpdateDate: 10,
            ServerSendsAnnounces: 11,
            ServerSendsExceptions: 12,
            ThereIsAnnounceChangeOnServerForU: 13,
            ClientRequestsAnnouncesForDevice: 14,
            ClientRequestLastPlayedSong: 15,
            ServerSendsLastPlayedSong: 16,
            ClientSendsLastPlayedSongs: 17,
            ClientSendSSHExeResult: 18,
            ServerSendSSHCmd: 19,
            ServerRequestSSHSessionStatus: 20,
            ClientSendStatusConnection: 21,
            ServerSendConnect: 22,
            ServerSendDisconnect: 23,
            ClientSendSSHSessionStatus: 24,
            ClientSendSSHConnectionError: 25,
            ClientSendSTDErr: 26,
            ServerSendAudio: 27,
            ServerSendStreamUrl: 28,
            ServerRequestsStreamUrlChange: 29,
            ClientRequestsStreamUrl: 30,
            ServerRequestsgetFolders: 31,
            ServerRequestgetFile: 32,
            ServerSendsFile: 33,
            ClientSendsFolders: 34,
            ClientSendsFile: 35,
            ServerRequestgetParentFolders: 36,
            ServerRequestDeleteFile: 37,
            AdminRequestsClientList: 38,
            AdminRequestsClientInfo: 39,
            UserInfo: 40,
            ServerRequestsAppVersion: 41,
            ClientSendsAppVersion: 42,
            ServerSendsAppUpdates: 43,
            ServerSendsThirdPartyApiKeys: 44,
            ServerRequestsPlaylog: 45,
            ClientSendsPlayLog: 46,
            ServerRequestsPlayerEventsChannel: 47,
            ClientSendsPlayerEventsChannel: 48,
            ClientSendsPlayerEvents: 49,
            ServerRequestsPlayerSpecificActions: 50,
            // v8.7.9 events
            ClientSendsAnnounceDownloads: 51,
            ClientSendsScheduleDownloads: 52,
            ClientAnnouncesInsert: 53,
            ClientSchedulesInsert: 54,
            ClientDownloadExInsert: 55,
            ClientTimeExInsert: 56,
            ClientGlobalExInsert: 57,
            ServerRequestsDeviceInfo: 58,
            ClientSendsDeviceInfo: 59,
            ServerRequestsDownloadStatus: 60,
            ClientSendsDownloadedData: 61



        };
        this._client = null;
        this._retry = retryConnect || true;
        this._channel = '/smg';
        this._url = connectionUrl || 'http://localhost:11037/smgpush';
        this._delayRetryFirst = this.config.ConnectRetry.First;
        this._delayRetrySecond = this.config.ConnectRetry.Second;
        this.isSubscribe = parseInt(this.config.SubscribeEvents.Subscribe);

        this._user = {
            IP: utils.getIPs().first().ip,
            ClientId: "00000000-0000-0000-0000-000000000000",
            username: "smg",
            password: "smg123",
            deviceID: config.Settings.deviceID,
            version: utils.appversion,
            isAdmin: false,
            deviceName: `smgplayer-${utils.getIPs().first().mac}`,
            userType: utils.osType,
            lastSeenDate: new moment().utc(true).toJSON().substr(0, 19)
        };


        //</editor-fold>

        xreq.setProxy(this._proxyOptions);


    }

    get url() {
        return this._url;
    }

    set url(newurl) {
        this._url = newurl
    }


    setProxy(value) {
        xreq.setProxy(value)
    }

    async setUser({IP, deviceID, deviceName, userType, version} = {}) {
        this._user.IP = IP;
        this._user.deviceID = deviceID;
        this._user.deviceName = deviceName;
        this._user.userType = userType;
        this._user.version = version;
        this._user.lastSeenDate = new moment().utc(true).format('MMMM DD YYYY,h:mm:ss a');


    }

    setPlayerEventsToPush(obj) {
        this.playerEventsToPush = obj;
    }

    //<editor-fold desc="Push notification">
    connect() {


        try {

            let u = JSON.stringify(enc.Encrypt(JSON.stringify(this._user)));
            logger.SyncConnection("connecting to: " + this._url);
            this._client = new fm.websync.client(this._url);
            this._client.addOnNotify((p) => {
                this.onNotify(p)
            });
            this._client.connect({
                MetaJson: u,
                onSuccess: (e) => {

                    this.emit(this.eventsTypes.ConnectionStatus, this.connectionStatusMessages.Connected, true);
                    logger.SyncConnection("PushNotification onSuccess: " + e.getConnectionType() + ", My ClientID : " + this._client.getClientId());
                    this.playerEventsToPush.setMyId(this._client.getClientId().toString());
                    this.playerEventsToPush.clearUsers();
                    this.subscribeToPlayerEventsChannel();
                },
                onFailure: (e) => {
                    this.playerEventsToPush.clearUsers();
                    this.emit(this.eventsTypes.ConnectionStatus, this.connectionStatusMessages.Failure, false);
                    logger.SyncConnection("PushNotification onFailure: " + e);
                    logger.SyncConnection("PushNotification onFailure: " + e.getErrorMessage() + ' ' + e.getErrorCode());
                    e.setRetry(this._retry);
                }, RetryBackoff: (e) => {
                    this.playerEventsToPush.clearUsers();
                    this.emit(this.eventsTypes.ConnectionStatus, this.connectionStatusMessages.Retrying, false);
                    logger.SyncConnection("PushNotification RetryBackoff: " + e);
                    if (e.Index == 0) {
                        return this._delayRetryFirst;
                    }
                    //return e.LastTimeout * 3;
                    return this._delayRetrySecond
                }
            });
        }
        catch (ex) {
            logger.SyncConnection('error decompressing schedules data:' + ex)
        }
    }

    async subscribeToPlayerEventsChannel() {
        let eventsChannel = '/playerEvents' + this.utils.serial;
        this.eventsChannel = eventsChannel;
        this.playerEventsToPush.setChannel(eventsChannel);
        logger.SyncConnection('PlayerEventsChannel', eventsChannel);
        if(this.isSubscribe==1) {
            this._client.subscribe({
                channel: eventsChannel,
                onSuccess: (e) => {
                    // subscribed!
                    var subscribedClients = e.getSubscribedClients()[eventsChannel];

                    for (var i = 0; i < subscribedClients.length; i++) {
                        var subscribedClient = subscribedClients[i];
                        var q1 = this._client.getClientId().toString();
                        var q2 = subscribedClient.getClientId().toString();
                        var q3 = this._client.getSubscribedChannels();
                        var q4 = this._client.getBoundRecords();
                        this.playerEventsToPush.addUser(subscribedClient.getClientId().toString());
                        if (this._client.getClientId().toString() == subscribedClient.getClientId().toString()) {
                            logger.SyncConnection('i am subscribed to channel')
                        }
                        // add subscribedClient.getClientId()/getBoundRecords()
                        // to list of subscribers
                    }
                    this.playerEventsToPush.sendInit();
                },
                onClientSubscribe: (e) => {
                    logger.SyncConnection('new subscriber added');
                    this.playerEventsToPush.addUser(e.getSubscribedClient().getClientId().toString());
                    this.playerEventsToPush.sendInit();
                    // client subscribed

                    // add e.getSubscribedClient().getClientId()/getBoundRecords()
                    // to list of subscribers
                },
                onClientUnsubscribe: (e) => {
                    logger.SyncConnection('subscriber closed');
                    this.playerEventsToPush.removeUser(e.getUnsubscribedClient().getClientId().toString())
                    // client unsubscribed

                    // remove e.getUnsubscribedClient().getClientId()/getBoundRecords()
                    // from list of subscribers
                }
                // ,
                // onReceive:(e)=>{
                //     var q1=e.getData()
                //     var q2=e.getDataJson()
                //     e.getData().message()
                // }
            });
        }
    }

    disconnect() {
        this._client.disconnect();
        this.emit(this.eventsTypes.ConnectionStatus, this.connectionStatusMessages.Disconnected, false)
    }

    async onNotify(p) {
        // let cl=p.getNotifyClientId()

        let command = parseInt(p.getTag());

        //console.log('on notify tag:', command, ', data:', p.getDataJson());
        this.emit(this.eventsTypes.NotifyEvent, p);

        switch (command) {
            case this._pushFunctions.ServerRequestsLastUpdateDate:
                this.emit(this.eventsTypes.ServerRequestsScheduleLastUpdateDate);
                await this.ProcessServerRequestsSchedulesLastUpdateDate(p);
                break;

            case this._pushFunctions.ServerSendsThirdPartyApiKeys:
                await this.ProcessThirdPartyApiKeys(p);
                break;
            case this._pushFunctions.ThereIsChangeOnServerForU:
                this.emit(this.eventsTypes.ThereIsScheduleChangeOnServer, p.getDataJson().replace(/"/g, ""));
                await this.ProcessThereIsScheduleChangeOnServerForU(p);
                break;
            case this._pushFunctions.ServerSendsSchedules:
                this.ProcessServerSendsSchedules(p);
                break;
            case this._pushFunctions.ServerRequestsAnnouncesLastUpdateDate:
                this.emit(this.eventsTypes.ServerRequestsAnnouncesLastUpdateDate);
                await this.ProcessServerRequestsAnnouncesLastUpdateDate(p);
                break;
            case this._pushFunctions.ThereIsAnnounceChangeOnServerForU:
                this.emit(this.eventsTypes.ThereIsAnnounceChangeOnServer, p.getDataJson().replace(/"/g, ""));
                await this.ProcessThereIsAnnounceChangeOnServerForU(p);
                break;
            case this._pushFunctions.ServerSendsAnnounces:
                await this.ProcessServerSendsAnnounces(p);
                break;
            case this._pushFunctions.ServerSendsExceptions:
                this.ProcessServerSendsExceptions(p);
                break;
            case this._pushFunctions.ServerSendsLastPlayedSong:
            //ProcessServerSendsLastPlayedSong(p);
            case this._pushFunctions.ServerRequestSSHSessionStatus:
                // ProcessServerRequestSSHSessionStatus(c);
                break;
            case this._pushFunctions.ServerSendConnect:
                //ProcessServerSendConnect(p);
                break;
            case this._pushFunctions.ServerSendDisconnect:
                //ProcessServerSendDisconnect(p);
                break;
            case this._pushFunctions.ServerSendSSHCmd:
                //ProcessServerSendSSHCmd(p);
                break;
            case this._pushFunctions.ServerSendAudio:
                this.ProcessServerSendAudio(p);
                break;
            case this._pushFunctions.ServerSendStreamUrl:
                await this.ProcessServerSendStreamUrl(p);
                break;
            case this._pushFunctions.ServerRequestsStreamUrlChange:
                this.emit(this.eventsTypes.ServerRequestsStreamUrlChange);
                this.RequestServerStreamUrl();
                break;
            case this._pushFunctions.ServerRequestsgetFolders:
                //ProcessServerRequestsgetFolders(p);
                break;
            case this._pushFunctions.ServerRequestgetFile:
                //ProcessServerRequestgetFile(p);
                break;
            case this._pushFunctions.ServerRequestgetParentFolders:
                //ProcessServerRequestgetParentFolders(p);
                break;
            case this._pushFunctions.ServerSendsFile:
                //ProcessServerSendsFile(p);
                break;
            case this._pushFunctions.ServerRequestDeleteFile:
                //ProcessServerRequestDeleteFile(p);
                break;
            case this._pushFunctions.ServerRequestsAppVersion:
                await this.ProcessServerRequestsAppVersion(p);
                break;
            case this._pushFunctions.ServerSendsAppUpdates:
                await this.ProcessServerSendsAppUpdates(p);
                break;
            case this._pushFunctions.ServerRequestsPlaylog:
                await this.ProcessServerRequestsPlaylog(p);
                break;
            case this._pushFunctions.ServerRequestsPlayerEventsChannel:
                await this.ProcessServerRequestsPlayerEventsChannel(p);
                break;
            case this._pushFunctions.ServerRequestsPlayerSpecificActions:
                await this.ProcessServerRequestsPlayerSpecificActions(p);
                break;
            case this._pushFunctions.ServerRequestsDeviceInfo:
                await this.ProcessServerRequestDeviceInfo(p);
                break;
            case this._pushFunctions.ServerRequestsDownloadStatus:
                await this.ProcessServerRequestsDownloadStatus(p);
                break;
            default :
                break;
        }
    }

    //</editor-fold>
    async ProcessServerRequestsPlayerSpecificActions(p) {
        let cl=p.getNotifyClientId();
        let command = parseInt(p.getTag());
        let data= p.getDataJson();

    }

    async ProcessServerRequestsPlayerEventsChannel(p) {
        let nclientID = p.getNotifyingClient().getClientId();
        await this.NotifyClient(nclientID, this.eventsChannel, this._pushFunctions.ClientSendsPlayerEventsChannel)
    }

    //<editor-fold desc="Push notification processes">


    async NotifyClient(clientId, dataToSend, tag) {
        return await (new Promise((resolve, reject) => {
            this._client.notify({
                clientId: clientId,
                data: JSON.stringify(dataToSend),
                Tag: JSON.stringify(tag),

                onFailure: (e) => {
                    logger.SyncConnection("notify client failure.");
                    logger.SyncConnection(e.getException().message);
                    resolve({msg: e.getException().message, sended: false})
                }
                ,
                onSuccess: (e) => {
                    resolve({msg: 'ok', sended: true})
                }
            });
        }))

    }

    async PublishMsg(channel, dataToSend, tag) {
        return await (new Promise((resolve, reject) => {
            this._client.publish({
                channel: channel,
                data: dataToSend,
                Tag: JSON.stringify(tag),

                onFailure: (e) => {
                    logger.SyncConnection("publish message failure");
                    logger.SyncConnection(e.getException().message);
                    resolve({msg: e.getException().message, sended: false})
                },
                onSuccess: (e) => {
                    resolve({msg: 'ok', sended: true})
                }
            });

        }));
    }

    async ProcessServerRequestsPlaylog(p) {


        let parsed = JSON.parse(JSON.parse(p.getDataJson()));
        let nclientID = p.getNotifyingClient().getClientId();
        //parsed.startDate,parsed.endDate,parsed.parsed.startTime,parsed.endTime,parsed.logType
        let mydata;
        //logtypes :0-schedules, 1-announces, 2-Time exceptions, 3-GlobalExceptions
        if (parsed.logType == 0 || parsed.logType == 1) {
            mydata = await this.logdb.getLogFromDate(parsed.startDate, parsed.endDate, parsed.startTime, parsed.endTime, parsed.logType)
        } else if (parsed.logType == 2) {
            mydata = await this.db.getTimeExceptions()
        } else if (parsed.logType == 3) {
            mydata = await this.db.getGlobalExceptions();
        }
        let data = {logType: parsed.logType, data: mydata};
        //let datastring=compressor.Compress( Buffer.from(JSON.stringify( data)).toString('base64'))
        let result = await this.NotifyClient(nclientID, data, this._pushFunctions.ClientSendsPlayLog);
        logger.SyncConnection(`playlog sent to ${nclientID}, status:${result.sended}`)
    }

    async ProcessServerRequestsDownloadStatus(p) {
        let downloaded = await this.db.getDownloadedWithDetails();
        let encrypted = enc.Encrypt(compressor.Compress(JSON.stringify(downloaded)));
        await this.PublishMsg(this._channel, encrypted, this._pushFunctions.ClientSendsDownloadedData);
    }

    //<editor-fold desc="App version control">
    async ProcessServerRequestsAppVersion(p) {
        let version = this.utils.appversion;
        await this.PublishMsg(this._channel, version, this._pushFunctions.ClientSendsAppVersion)
    }

    ProcessServerSendsAppUpdates(p) {
        let parsed = JSON.parse(p.getDataJson());
        this.emit(this.eventsTypes.AppUpdateReceived, parsed)
    }

    //</editor-fold>

    //<editor-fold desc="push audio">
    ProcessServerSendAudio(p) {
        let parsed = JSON.parse(p.getDataJson());
        logger.PushAudio('new pushaudio received from server' + parsed);
        this.emit(this.eventsTypes.PushAudioReceived, parsed)
    }

    //</editor-fold>

    //<editor-fold desc="Stream Url processes">
    async ProcessServerSendStreamUrl(p) {
        let parsed = JSON.parse(p.getDataJson());
        logger.StreamUrl('new stream url update received from server:' + parsed);
        await this.db.InsertStreamUrl(parsed);
    }

    RequestServerStreamUrl() {
        this._client.publish({
            channel: this._channel,
            data: "",
            Tag: this._pushFunctions.ClientRequestsStreamUrl.toString()
        });
    }

    //</editor-fold>

    //<editor-fold desc="Announces push notifications and processing part">

    async ProcessServerRequestsAnnouncesLastUpdateDate(p) {
        //get last update date from db
        let lastUpdateDate = await this.announcesdb.getAnnouncesLastUpdate();
        logger.SyncConnection('Announces LastUpdateDate on local was:' + lastUpdateDate);

        if (!lastUpdateDate) {
            lastUpdateDate = new moment().utc(true).toJSON().substr(0, 19)

        }

        logger.SyncConnection('sending last announce update date of local:' + lastUpdateDate);
        await this.SendServerAnnouncesLastUpdateDate(lastUpdateDate)

    }

    async SendServerAnnouncesLastUpdateDate(dt) {
        await this._client.publish({
            channel: this._channel,
            data: dt,
            Tag: this._pushFunctions.ClientSendsAnnouncesLastUpdateDate.toString()
        });
    }

    async ProcessThereIsAnnounceChangeOnServerForU(p) {
        let serverChangeDate = p.getDataJson().replace(/"/g, "").substr(0, 19);
        let dbChangeDate = await this.announcesdb.getAnnouncesLastUpdate();
        logger.SyncConnection('Announces LastUpdateDate received from server:' + serverChangeDate + ', db date was:' + dbChangeDate);
        if (!dbChangeDate) {
            //if there is no record on db then request
            logger.SyncConnection('we dont have any AnnounceData on db, requesting it from server.');
            this.RequestAnnouncesFromServer();
        } else if (dbChangeDate != serverChangeDate) {
            //our records are different then server, request data
            logger.SyncConnection('lastUpdateDate of Announces is different from server, requesting it from server');
            this.RequestAnnouncesFromServer();
        }
        else {
            //last update date is same with db.. skip..
            logger.SyncConnection('lastupdateDate of Announces is same with server, skipping request..')

        }

    }

    RequestAnnouncesFromServer() {
        this._client.publish({
            channel: this._channel,
            data: this._user.deviceID,
            Tag: this._pushFunctions.ClientRequestsAnnouncesForDevice.toString()
        });
    }

    async ProcessServerSendsAnnounces(p) {
        logger.SyncConnection('server sends new announces ');
        if (p.getIsBinary) {
            let data = p.getDataJson();
            try {
                let decdata = JSON.parse(compressor.Decompress(data));
                await this.announcesdb.InsertAnnounces(decdata);

            }
            catch (ex) {
                logger.SyncConnection('error decompressing Announces data:' + ex)
            }

        }
    }

    //</editor-fold>

    //<editor-fold desc="Schedules push notification processes">

    async ProcessServerRequestsSchedulesLastUpdateDate(p) {
        //get last update date from db
        let lastUpdateDate = await this.schedulesdb.getSchedulesLastUpdateDate();
        logger.SyncConnection('Schedules LastUpdateDate was:' + lastUpdateDate);
        if (!lastUpdateDate) {
            lastUpdateDate = new moment().utc(true).toJSON().substr(0, 19)

        }

        logger.SyncConnection('sending last schedules update date:' + lastUpdateDate);
        await this.SendServerSchedulesLastUpdateDate(lastUpdateDate)
    }

    async SendServerSchedulesLastUpdateDate(dt) {
        await this._client.publish({
            channel: this._channel,
            data: dt,
            Tag: this._pushFunctions.ClientSendsLastUpdateDate.toString()
        });
    }

    // v8.7.9 features start
    async SendServerDownloadStatus(data, type) {
        if(this._client && data && data.length) {
            let json = enc.Encrypt(compressor.Compress(JSON.stringify(data)));
            await this._client.publish({
                channel: this._channel,
                data: json,
                Tag: type.toString()
            });
        }
    }

    // async SendServerListUpdateStatus(data) {
    //     if(this._client && data) {
    //         await this._client.publish({
    //             channel: this._channel,
    //             data: data,
    //             Tag: this._pushFunctions.ClientSendsListUpdate.toString()
    //         });
    //     }
    // }

    async SendServerExceptionStatus(type) {
            await this._client.publish({
                channel: this._channel,
                data: '',
                Tag: type.toString()
            });
    }

    async SendServerDatabaseInsert(type) {
            try {
                await this._client.publish({
                    channel: this._channel,
                    data: '',
                    Tag: type.toString()
                })
            } catch (e) {

            }
    }

    async ProcessServerRequestDeviceInfo(p) {
        let nclientID = p.getNotifyingClient().getClientId();
        let info = require('../utils/getDeviceInfo');
        let devInfo = await info();
        let encJSON = enc.Encrypt(compressor.Compress(JSON.stringify(devInfo)));
        let result = await this.NotifyClient(nclientID, encJSON, this._pushFunctions.ClientSendsDeviceInfo);
        logger.SyncConnection(`device info sent to ${nclientID}, status:${result.sended}`);
        devInfo = null;
    }

    // v8.7.9 features end

    async ProcessThereIsScheduleChangeOnServerForU(p) {
        let serverChangeDate = p.getDataJson().replace(/"/g, "").substr(0, 19);
        let dbChangeDate = await this.schedulesdb.getSchedulesLastUpdateDate();
        logger.SyncConnection('Schedules LastUpdateDate received from server:' + serverChangeDate + ', db date was:' + dbChangeDate);
        if (!dbChangeDate) {
            //if there is no record on db then request
            logger.SyncConnection('we dont have any ScheduleData on db, requesting it from server.');
            this.RequestSchedulesFromServer();
        } else if (dbChangeDate != serverChangeDate) {
            //our records are different then server, request data
            logger.SyncConnection('lastUpdateDate of Schedules is different from server, requesting it from server');
            this.RequestSchedulesFromServer();
        }
        else {
            //last update date is same with db.. skip..
            logger.SyncConnection('lastupdateDate of Schedules is same with server, skipping request..')

        }
    }

    RequestSchedulesFromServer() {
        this._client.publish({
            channel: this._channel,
            data: this._user.deviceID,
            Tag: this._pushFunctions.ClientRequestsSchedulesForDevice.toString()
        });
    }

    async ProcessServerSendsSchedules(p) {
        logger.SyncConnection('server sends new Schedules ');
        if (p.getIsBinary) {
            let data = p.getDataJson();
            try {
                let decdata = JSON.parse(compressor.Decompress(data));
                await this.schedulesdb.InsertSchedules(decdata);

            }
            catch (ex) {
                logger.SyncConnection('error decompressing Schedules data:' + ex)
            }

        }
    }

    //</editor-fold>

    async ProcessServerSendsExceptions(p) {

        let self = this;
        let db = this.db;
        if (p.getIsBinary) {
            let data = p.getDataJson();
            //logger.SyncConnection(("data received:" + data));

            try {
                let decdata = JSON.parse(compressor.Decompress(data));
                await this.db.InsertExceptions(decdata);
                this.emit("ExceptionsReceivedFromServer", decdata);
            }
            catch (ex) {
                logger.SyncConnection('error decompressing exception data:' + ex)
            }
        } else {
            logger.SyncConnection("there is problem on getting server Exceptions");
        }

    }
    async ProcessThirdPartyApiKeys(p) {
        logger.SyncConnection(`Third party apikey recieved`);
        let data = JSON.parse(p.getDataJson());
        this.emit(this.eventsTypes.ThirdPartyApiKeys, data);
    }

    //</editor-fold>


}

const EventEmitter = require('events').EventEmitter;
util.inherits(SMGPush, EventEmitter);

module.exports = SMGPush;
