import { NativeEventEmitter, DeviceEventEmitter, NativeModules, Platform } from 'react-native';
import { MPosControllerBase } from "./MPosControllerBase"
import { APIResponse } from "./constants/APIResponse";

const { MPosControllerDevicesProxy } = NativeModules

export class MPosControllerDevices implements MPosControllerBase {
    private statusEventEmitter: NativeEventEmitter = new NativeEventEmitter(MPosControllerDevicesProxy);
    private outputCompletedEventEmitter: NativeEventEmitter = new NativeEventEmitter(MPosControllerDevicesProxy);
    private dataEventEmitter: NativeEventEmitter = new NativeEventEmitter(MPosControllerDevicesProxy);

    statusUpdatedEventCallback?: (deviceid: number, status: number) => void;
    outputCompletedEvent?: (deviceid: number) => void;
    dataEvent?: (deviceid: number, data: Array<number>) => void;

    private readonly isWindows: boolean;

    constructor() {
        this.isWindows = Platform.OS === 'windows';

        if (Platform.OS === 'ios') {
            this.statusEventEmitter.addListener("StatusUpdateEvent", (event) => {
                // object format: "{status: 0, deviceid: -1 }"
                console.log('MPosControllerPrinter: StatusUpdateEvent fired');
                console.info(event);
                if (!this.statusUpdatedEventCallback) { return; }
                this.statusUpdatedEventCallback(event.deviceid, event.status);
            })
            this.outputCompletedEventEmitter.addListener("OutputCompletedEvent", (event) => {
                console.log('MPosControllerPrinter: outputCompletedEvent fired');
                if (!this.outputCompletedEvent) { return; }
                this.outputCompletedEvent(event.deviceid);
            })
            this.dataEventEmitter.addListener("DevicesDataEvent", (event) => {
                console.log('MPosControllerPrinter: dataEvent fired');
                if (!this.dataEvent) { return; }
                this.dataEvent(event.deviceid, event.data);
            })
        } else {
            DeviceEventEmitter.addListener("StatusUpdateEvent", (event) => {
                // object format: "{status: 0, deviceid: -1 }"
                console.log('MPosControllerPrinter: StatusUpdateEvent fired');
                console.info(event);
                if (!this.statusUpdatedEventCallback) { return; }
                this.statusUpdatedEventCallback(event.deviceid, event.status);
            });
            DeviceEventEmitter.addListener("OutputCompletedEvent", (event) => {
                console.log('MPosControllerPrinter: OutputCompletedEvent fired');
                if (!this.outputCompletedEvent) { return; }
                this.outputCompletedEvent(event.deviceid);
            });
            DeviceEventEmitter.addListener("DevicesDataEvent", (event) => {
                console.log('MPosControllerPrinter: dataEvent fired');
                if (!this.dataEvent) { return; }
                this.dataEvent(event.deviceid, event.data);
            });
        }
    }

    async selectInterface(interfaceType: number, adddress: string): Promise<number> {
        try {
            if (this.isWindows) {
                return await MPosControllerDevicesProxy.selectInterface([interfaceType, adddress]);
            } else {
                return await MPosControllerDevicesProxy.selectInterface(Number(interfaceType), adddress);
            }
        } catch (e) {
            return APIResponse.RES_FAIL;
        }
    }

    async selectCommandMode(commandMode: number): Promise<number> {
        try {
            return await MPosControllerDevicesProxy.selectCommandMode(Number(commandMode));
        } catch (e) {
            return APIResponse.RES_FAIL;
        }
    }

    async openService(deviceID: number, timeout: number): Promise<number> {
        try {
            if (this.isWindows) {
                return await MPosControllerDevicesProxy.openService([deviceID, timeout]);
            } else {
                return await MPosControllerDevicesProxy.openService(Number(deviceID), timeout);
            }
        } catch (e) {
            return APIResponse.RES_FAIL;
        }
    }

    async closeService(timeout: number): Promise<number> {
        try {
            return await MPosControllerDevicesProxy.closeService(timeout);
        } catch (e) {
            return APIResponse.RES_FAIL;
        }
    }

    async isOpen(): Promise<number> {
        try {
            return await MPosControllerDevicesProxy.isOpen();
        } catch (e) {
            return 0;
        }
    }

    async getDeviceId(): Promise<number> {
        try {
            return await MPosControllerDevicesProxy.getDeviceId();
        } catch (e) {
            return -1;
        }
    }

    async directIO(data: Array<number>): Promise<number> {
        try {
            return await MPosControllerDevicesProxy.directIO(data);
        } catch (e) {
            return -1;
        }
    }

    async setTransaction(mode: number): Promise<number> {
        try {
            return await MPosControllerDevicesProxy.setTransaction(mode);
        } catch (e) {
            return APIResponse.RES_FAIL;
        }
    }

    async setReadMode(mode: number): Promise<number> {
        try {
            return await MPosControllerDevicesProxy.setReadMode(mode);
        } catch (e) {
            return APIResponse.RES_FAIL;
        }
    }

    async setKeepNetworkConnection(mode: number): Promise<number> {
        try {
            return await MPosControllerDevicesProxy.setKeepNetworkConnection(mode);
        } catch (e) {
            return APIResponse.RES_FAIL;
        }
    }

    async getSDKVersion(): Promise<string> {
        try {
            return await MPosControllerDevicesProxy.getSDKVersion();
        } catch (e) {
            return "";
        }
    }

     async getOccuredData(): Promise<Array<number>|null> {
        try {
            return await MPosControllerDevicesProxy.getOccuredData();
        } catch (e) {
            return Promise.resolve(null);
        }
     }
}