package it.integry.keyobardemulatorscannerlibrary;

import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.util.Pair;
import android.view.KeyEvent;

import java.util.List;

import it.integry.barcode_base_android_library.exception.BarcodeAdapterNotFoundException;
import it.integry.barcode_base_android_library.extension.RunnableArgs;
import it.integry.barcode_base_android_library.interfaces.BarcodeReaderInterface;
import it.integry.barcode_base_android_library.model.BarcodeScanDTO;
import it.integry.barcode_base_android_library.model.BarcodeType;

public class KeyboardEmulatorBarcodeReader implements BarcodeReaderInterface {

    private String barcode;
    private RunnableArgs<BarcodeScanDTO> mOnScanSuccessfull;
    private RunnableArgs<Exception> mOnScanFailed;
    private String mTextBarcode = "";
    private final Handler handler = new Handler(Looper.getMainLooper());
//    private long mLastCharInsertTime = 0;


    public KeyboardEmulatorBarcodeReader(Context applicationContext) {

    }

    @Override
    public boolean isRightAdapter() {
        return true;
    }

    @Override
    public void init(Runnable onDeviceReady) throws BarcodeAdapterNotFoundException {
        onDeviceReady.run();
    }

    @Override
    public void deinit() {

    }

    @Override
    public void register(RunnableArgs<BarcodeScanDTO> onScanSuccessfull, RunnableArgs<Exception> onScanFailed) {
        mOnScanSuccessfull = onScanSuccessfull;
        mOnScanFailed = onScanFailed;
    }

    @Override
    public String getAdapterName() {
        return "KeyboardEmulator";
    }

    @Override
    public void onKeyEvent(KeyEvent keyEvent) {

//        if (keyEvent.getEventTime() - mLastCharInsertTime > 500) {
//            mLastCharInsertTime = keyEvent.getEventTime();
//            mTextBarcode = "";
//        }
//        if (keyEvent.getKeyCode() != KeyEvent.KEYCODE_ENTER) {
//            if (keyEvent.getKeyCode() != KeyEvent.KEYCODE_SHIFT_LEFT) {
//                mLastCharInsertTime = keyEvent.getEventTime();

        handler.removeCallbacks(dispatchBarcode);

        if (keyEvent.getUnicodeChar() > 0) {
            mTextBarcode += (char) keyEvent.getUnicodeChar();
        } else if (keyEvent.getCharacters() != null) {
            mTextBarcode = keyEvent.getCharacters();
        }

        handler.postDelayed(dispatchBarcode, 500);
//            }
//        } else {
//            if (mTextBarcode.length() > 0) {
//
//                BarcodeType barcodeType = decodeBarcode(mTextBarcode);
//                BarcodeScanDTO barcodeScanDTO = new BarcodeScanDTO()
//                        .setByteValue(mTextBarcode.getBytes())
//                        .setStringValue(mTextBarcode)
//                        .setType(barcodeType)
//                        .setName(barcodeType != null ? barcodeType.toString() : "");
//
//                mOnScanSuccessfull.run(barcodeScanDTO);
//            }
//        }

    }


    private final Runnable dispatchBarcode = new Runnable() {
        @Override
        public void run() {
            BarcodeType barcodeType = decodeBarcode(mTextBarcode);
            BarcodeScanDTO barcodeScanDTO = new BarcodeScanDTO()
                    .setByteValue(mTextBarcode.getBytes())
                    .setStringValue(mTextBarcode)
                    .setType(barcodeType)
                    .setName(barcodeType != null ? barcodeType.toString() : "");

            mOnScanSuccessfull.run(barcodeScanDTO);
            mTextBarcode = "";
        }
    };

    public BarcodeType decodeBarcode(String barcode) {
        /*Pattern patternUPCA = Pattern.compile("^[0-9]{12}$");
        Pattern patternUPCE = Pattern.compile("^[0-1][0-9]{7}$");
        Pattern patternUPCE1 = Pattern.compile("");
        Pattern patternEAN8 = Pattern.compile("^[0-9]{8}$");
        Pattern patternEAN13 = Pattern.compile("^[0-9]{13}$");
        Pattern patternCODE11 = Pattern.compile("");
        Pattern patternCODE39 = Pattern.compile("");*/
        if (barcode.length() == 8) {
            try {
                int checksum = getEanChecksum(barcode);
                if (checksum == Integer.parseInt(barcode.substring(7))) {
                    return BarcodeType.EAN8;
                }
            } catch (WrongFormatException e) {
                return BarcodeType.CODE128;
            }
        } else if (barcode.length() == 13) {
            try {
                int checksum = getEanChecksum(barcode);
                if (checksum == Integer.parseInt(barcode.substring(12))) {
                    return BarcodeType.EAN13;
                }
            } catch (WrongFormatException e) {
                return BarcodeType.CODE128;
            }
        } else if (barcode.length() == 14) {
            try {
                int checksum = getEanChecksum(barcode);
                if (checksum == Integer.parseInt(barcode.substring(13))) {
                    return BarcodeType.INTERLEAVED_2OF5;
                }
            } catch (WrongFormatException e) {
                return BarcodeType.CODE128;
            }
        }
        return BarcodeType.CODE128;
    }

    private static int getEanChecksum(String barcode) throws WrongFormatException {
        int odds = 0;
        int evens = 0;
        barcode = barcode.substring(0, barcode.length() - 1);
        int pos = 0;
        for (int i = barcode.length() - 1; i >= 0; i--) {
            pos++;
            if (!Character.isDigit(barcode.charAt(i))) {
                throw new WrongFormatException();
            }
            if (pos % 2 == 0) {
                evens += Integer.parseInt(barcode.charAt(i) + "");
            } else {
                odds += Integer.parseInt(barcode.charAt(i) + "");
            }
        }
        return ((10 - (((3 * odds) + evens) % 10)) % 10);
    }

    @Override
    public void changeSettings(List<Pair<String, Object>> settings) {

    }
}
