package com.cocodin.barcodescan.plugin;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;

import com.zebra.adc.decoder.Barcode2DWithSoft;

import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.PluginResult;
import org.apache.cordova.PluginResult.Status;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.IntentFilter;
import com.honeywell.aidc.AidcManager.CreatedCallback;

import com.phonegap.plugins.barcodescanner.BarcodeScanner;

import android.content.Context;
import android.content.pm.ActivityInfo;
import android.util.Log;
import android.widget.ListView;
import android.widget.Toast;
import com.honeywell.aidc.*;

public class PluginHelper {

    private static final String TAG = "PluginHelper";
    private static boolean threadStop = true;
    private static ExecutorService executor;
    private static Barcode2DWithSoft mInstance;
    private static boolean MQuireOn = false;
    private static BroadcastReceiver barcodeScannerBroadcastReceiver;
    private static JSONArray Devices = new JSONArray().put("camera").put("c4050").put("NQuire300").put("EDA50K");
    private static CallbackContext cbContext;
    private static BarcodeReader barcodeReader;
    private static AidcManager manager;

    public static void scan(final CordovaInterface cordova, CordovaWebView webView, JSONArray args,
            final CallbackContext callbackContext) {
        String device = "";
        try {
            device = args.get(0).toString();
            if (device.equalsIgnoreCase(Devices.getString(1))) {
                Context context = cordova.getActivity();
                try {
                    mInstance = Barcode2DWithSoft.getInstance();
                    if (mInstance != null) {
                        mInstance.open(context);
                    }
                } catch (Exception e) {
                    Log.e(TAG, e.getMessage());
                    callbackContext.sendPluginResult(new PluginResult(Status.ERROR, e.getMessage()));
                }
                mInstance.setScanCallback(new Barcode2DWithSoft.ScanCallback() {
                    @Override
                    public void onScanComplete(int i, int length, byte[] data) {
                        Log.i(TAG, "onScanComplete() i=" + i);

                        if (length < 1) {
                            return;
                        }

                        String barCode = new String(data);
                        barCode = barCode.replaceAll("\u0000", "");
                        Log.i(TAG, barCode);

                        try {
                            JSONObject result = new JSONObject().put("text", barCode);
                            callbackContext.sendPluginResult(new PluginResult(Status.OK, result));
                        } catch (JSONException e) {
                            callbackContext.sendPluginResult(new PluginResult(Status.ERROR, e.getMessage()));
                        }
                    }
                });

                mInstance.scan();
            } else if (device.equalsIgnoreCase(Devices.getString(0))) {
                BarcodeScanner barcodeScanner = new BarcodeScanner();
                barcodeScanner.cordova = cordova;
                barcodeScanner.webView = webView;
                barcodeScanner.execute("scan", new JSONArray(), callbackContext);

            } else if (device.equalsIgnoreCase(Devices.getString(2))) {
                Context context = cordova.getActivity();
                cbContext = callbackContext;
                if (!MQuireOn) {
                    initMquire(context);
                }
            } else if (device.equalsIgnoreCase(Devices.getString(3))) {

                final Context context = cordova.getActivity();
                AidcManager.create(context, new CreatedCallback() {
                    @Override
                    public void onCreated(AidcManager aidcManager) {
                        manager = aidcManager;
                        barcodeReader = manager.createBarcodeReader();

                        if (barcodeReader != null) {

                            // register bar code event listener
                            barcodeReader.addBarcodeListener(new BarcodeReader.BarcodeListener() {
                                @Override
                                public void onBarcodeEvent(BarcodeReadEvent barcodeReadEvent) {
                                    callbackContext.sendPluginResult(
                                            new PluginResult(Status.OK, barcodeReadEvent.getBarcodeData()));
                                }

                                @Override
                                public void onFailureEvent(BarcodeFailureEvent barcodeFailureEvent) {
                                    callbackContext.sendPluginResult(
                                            new PluginResult(Status.ERROR, barcodeFailureEvent.toString()));
                                }
                            });

                            // set the trigger mode to client control
                            try {
                                barcodeReader.setProperty(BarcodeReader.PROPERTY_TRIGGER_CONTROL_MODE,
                                        BarcodeReader.TRIGGER_CONTROL_MODE_CLIENT_CONTROL);
                            } catch (UnsupportedPropertyException e) {
                                callbackContext
                                        .sendPluginResult(new PluginResult(Status.ERROR, "Failed to apply properties"));
                            }
                            // register trigger state change listener
                            barcodeReader.addTriggerListener(new BarcodeReader.TriggerListener() {
                                @Override
                                public void onTriggerEvent(TriggerStateChangeEvent event) {
                                    try {
                                        // only handle trigger presses
                                        // turn on/off aimer, illumination and decoding
                                        barcodeReader.aim(event.getState());
                                        barcodeReader.light(event.getState());
                                        barcodeReader.decode(event.getState());

                                    } catch (ScannerNotClaimedException e) {
                                        e.printStackTrace();
                                    } catch (ScannerUnavailableException e) {
                                        e.printStackTrace();
                                    }
                                }
                            });
                            Map<String, Object> properties = new HashMap<String, Object>();
                            // Set Symbologies On/Off
                            properties.put(BarcodeReader.PROPERTY_CODE_128_ENABLED, true);
                            properties.put(BarcodeReader.PROPERTY_GS1_128_ENABLED, true);
                            properties.put(BarcodeReader.PROPERTY_QR_CODE_ENABLED, true);
                            properties.put(BarcodeReader.PROPERTY_CODE_39_ENABLED, true);
                            properties.put(BarcodeReader.PROPERTY_DATAMATRIX_ENABLED, true);
                            properties.put(BarcodeReader.PROPERTY_UPC_A_ENABLE, true);
                            properties.put(BarcodeReader.PROPERTY_EAN_13_ENABLED, false);
                            properties.put(BarcodeReader.PROPERTY_AZTEC_ENABLED, false);
                            properties.put(BarcodeReader.PROPERTY_CODABAR_ENABLED, false);
                            properties.put(BarcodeReader.PROPERTY_INTERLEAVED_25_ENABLED, false);
                            properties.put(BarcodeReader.PROPERTY_PDF_417_ENABLED, false);
                            // Set Max Code 39 barcode length
                            properties.put(BarcodeReader.PROPERTY_CODE_39_MAXIMUM_LENGTH, 10);
                            // Turn on center decoding
                            properties.put(BarcodeReader.PROPERTY_CENTER_DECODE, true);
                            // Disable bad read response, handle in onFailureEvent
                            properties.put(BarcodeReader.PROPERTY_NOTIFICATION_BAD_READ_ENABLED, false);
                            // Apply the settings
                            barcodeReader.setProperties(properties);
                        }
                    }
                });
            }
        } catch (JSONException e) {
            e.printStackTrace();
            callbackContext.sendPluginResult(new PluginResult(Status.ERROR, ""));
        }
    }

    public static void getDevices(CordovaInterface cordova, CordovaWebView webView, JSONArray args,
            final CallbackContext callbackContext) {
        callbackContext.sendPluginResult(new PluginResult(Status.OK, Devices));
    }

    public static void initMquire(Context context) {
        Intent intent = new Intent("ACTION_BAR_SCANCFG");
        intent.putExtra("EXTRA_SCAN_MODE", 3);
        intent.putExtra("EXTRA_SCAN_AUTOENT", 0);
        intent.putExtra("EXTRA_SCAN_NOTY_LED", 1);
        intent.putExtra("EXTRA_SCAN_NOTY_SND", 1);
        context.sendBroadcast(intent);
        MQuireOn = true;
        barcodeScannerBroadcastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                final String scanResult_1 = intent.getStringExtra("SCAN_BARCODE1");
                final String scanStatus = intent.getStringExtra("SCAN_STATE");
                if (null == scanResult_1 || null == scanStatus || scanResult_1.isEmpty() || scanStatus.isEmpty()) {
                    return;
                }

                if ("ok".equals(scanStatus)) {
                    cbContext.success(scanResult_1);
                }
            }
        };
        context.registerReceiver(barcodeScannerBroadcastReceiver, new IntentFilter("nlscan.action.SCANNER_RESULT"));
    }
}
