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

const { MPosControllerNFCProxy } = NativeModules

export class MPosControllerNFC implements MPosControllerBase {
    private dataEventEmitter: NativeEventEmitter = new NativeEventEmitter(MPosControllerNFCProxy);

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

    private readonly isWindows: boolean;

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

        if (Platform.OS === 'ios') {
            this.dataEventEmitter.addListener("NFCDataEvent", (event) => {
                console.log('MPosControllerNFCProxy: dataEvent fired');
                if (!this.dataEvent) { return; }
                this.dataEvent(event.deviceid, event.data);
            })
        } else if (Platform.OS === 'windows') {
            DeviceEventEmitter.addListener("NFCDataEvent", (event) => {
                console.log('MPosControllerNFCProxy: dataEvent fired');

                const [deviceid, data] = event;
                event.deviceid = deviceid;
                event.data = data;

                if (!this.dataEvent) { return; }
                this.dataEvent(event.deviceid, event.data);
            })
        } else {
            DeviceEventEmitter.addListener("NFCDataEvent", (event) => {
                console.log('MPosControllerNFCProxy: 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 MPosControllerNFCProxy.selectInterface([interfaceType, adddress]);
            } else {
                return await MPosControllerNFCProxy.selectInterface(Number(interfaceType), adddress);
            }
        } catch (e) {
            return APIResponse.RES_FAIL;
        }
    }

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

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

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

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

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

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

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

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

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

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

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