import { baseBX24 } from "./base/BX24";
import { AuthBaseServe, logger } from "./types/authBaseServe";
import {getAuth} from './types/getAuth';
import { CallResult } from "./callResult";
import { BitrixEvent } from "./types/bitrixEvent";


export class BX24Server extends baseBX24{

    logger:logger=console;

    constructor(param: AuthBaseServe){
        super();

        if (param.auth_connector)
            this.AUTH_CONNECTOR=param.auth_connector;
            
        if (param.logger)
            this.logger=param.logger;

        this.IS_ADMIN=param.isAdmin===false?false:true;
        this.DOMAIN=param.domain;
        if (param.member_id){
            this.MEMBER_ID=param.member_id;
        }
        this.AUTH_EXPIRES=param.expires_in??0;
        this.REFRESH_ID=param.refresh_token;
        this.PROTOCOL=1;
        this.AUTH_ID=param.access_token;


        this.CLIENT_ID=param.client_id;
        this.CLIENT_SECRET=param.client_secret;
        this.isInit=true;
    }

    getOfflineEvents(debug=false, clear=true, authConnector=''):Promise<CallResult>{
        return new Promise((resolve)=>{
            try {
                if (debug){
                    this.callMethod('event.offline.list', {auth_connector:authConnector}, ress=>{
                        if (ress.error()){
                            const result=new CallResult({error_description:String(ress.error())}, {
                                data:[debug?{auth_connector:authConnector}:{clear:clear?1:0, auth_connector:authConnector}],
                                method:debug?'event.offline.list':'event.offline.get'
                            },this, 500);
                            resolve(result);
                        }
                        if (!ress.answer) ress.answer={};
                        if (!ress.answer.result) ress.answer.result={};
                        ress.answer.result={events:this.formatEvents(ress?.answer?.result||[])};
                        resolve(ress);
                    });
                }
                else{
                    this.callMethod('event.offline.get', {clear:clear?1:0, auth_connector:authConnector}, ress=>{
                        if (ress.error()){
                            const result=new CallResult({error_description:String(ress.error())}, {
                                data:[debug?{auth_connector:authConnector}:{clear:clear?1:0, auth_connector:authConnector}],
                                method:debug?'event.offline.list':'event.offline.get'
                            },this, 500);
                            resolve(result);
                        }
                        if (!ress.answer) ress.answer={};
                        if (!ress.answer.result) ress.answer.result={};
                        ress.answer.result.events=this.formatEvents(ress?.answer?.result?.events||[]);
                        resolve(ress);
                    })
                }
            } catch (err) {
                const result=new CallResult({error_description:String(err)}, {
                    data:[debug?{auth_connector:authConnector}:{clear:clear?1:0, auth_connector:authConnector}],
                    method:debug?'event.offline.list':'event.offline.get'
                },this, 500);
                resolve(result);
            }
            
        });
    }


        // arrOfflineEvents [
        //   {
        //     ID: '133245',
        //     TIMESTAMP_X: '2022-07-17T15:23:56+03:00',
        //     EVENT_NAME: 'ONTASKUPDATE',
        //     EVENT_DATA: {
        //       FIELDS_BEFORE: [Object],
        //       FIELDS_AFTER: [Object],
        //       IS_ACCESSIBLE_BEFORE: 'undefined',
        //       IS_ACCESSIBLE_AFTER: 'undefined'
        //     },
        //     EVENT_ADDITIONAL: { user_id: '41' },
        //     MESSAGE_ID: '3d1c2a472b1c775f4d80a1c5918aa3c8',
        //     PROCESS_ID: 'yxq61pfx5ikr7xw4csc6gsox9m3i1q8p',
        //     ERROR: '0'
        //   }
        // ]
    formatEvents(rawEvents:any):BitrixEvent[]{
        const result:BitrixEvent[]=[];
        for (const idx in rawEvents){
            const tempEvent:BitrixEvent={
                ID:Number(rawEvents[idx].ID),
                TIMESTAMP_X:new Date(rawEvents[idx].TIMESTAMP_X),
                EVENT_NAME:rawEvents[idx].EVENT_NAME                
            }
            if (rawEvents[idx].EVENT_DATA)
                tempEvent.EVENT_DATA=rawEvents[idx].EVENT_DATA;
            
            if (rawEvents[idx].EVENT_ADDITIONAL)
                tempEvent.EVENT_ADDITIONAL=rawEvents[idx].EVENT_ADDITIONAL;
            
            if (rawEvents[idx].MESSAGE_ID)
                tempEvent.MESSAGE_ID=rawEvents[idx].MESSAGE_ID;

            if (rawEvents[idx].PROCESS_ID)
                tempEvent.PROCESS_ID=rawEvents[idx].PROCESS_ID;

            if (rawEvents[idx].ERROR)
                tempEvent.ERROR=Boolean(Number(rawEvents[idx].ERROR));
            
            result.push(tempEvent);
        }
        return result;
    }

    runCallback(e:MessageEvent){
        this.logger.debug('callBack not allowed in server!', e);
    }

    onRefresh(cb:(params:getAuth)=>void){
        this.addEvent('refreshAuth', cb);
    }

    refreshAuth(cb?:CallableFunction){
        this.refreshAuthAsync()
        .then(newAuth=>{
            if (cb) cb(newAuth);
        })
        .catch(err=>{
            if (cb) cb(err);
        });
    }

    refreshAuthAsync():Promise<getAuth> {
        return new Promise((resolve, reject) => {
            this.call("https://oauth.bitrix.info/oauth/token/", {
                method:'refresh_token',
                data:{
                    grant_type: 'refresh_token',
                    client_id: this.CLIENT_ID,
                    client_secret: this.CLIENT_SECRET,
                    refresh_token: this.REFRESH_ID
                }
            })
            .then(data=>{
                this.AUTH_ID=data.answer.access_token;
                this.REFRESH_ID=data.answer.refresh_token;
                this.AUTH_EXPIRES=data.answer.expires*1000;
                this.emitEvent('refreshAuth', this.getAuth());
                const authArr=this.getAuth();
                if (authArr===false){
                    reject('Refresh auth undefined error!');
                }
                else{
                    resolve(authArr);
                }
            })
            .catch(err=>{
                reject (err);
            })
        });
    }



    sendMessage(cmd: string, params: any, cb?: CallableFunction): void {
        this.logger.log('sendMessage',{
            cmd:cmd,
            params:params,
            cb:cb
        });
        if (cb) cb();
    }
}