//  EMVTransactionFragment.java
//  Sample App for PaymentSDK
//
//  Created by Samstaurej Siddiquie on 23/10/2019.
//  Copyright © 2019 Zeamster. All rights reserved.

package com.zeamster.sampleapp;

import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.text.method.ScrollingMovementMethod;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.Fragment;

import com.idtechproducts.device.ReaderInfo;
import com.zeamster.paymentsdk.resthandler.ICallback;
import com.zeamster.paymentsdk.transaction.EMVTransaction;
import com.zeamster.paymentsdk.transaction.ICallbackEMV;

import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.Objects;

import static com.zeamster.sampleapp.MainActivity.payload;
import static com.zeamster.sampleapp.MainActivity.transactionAction;

public class EMVTransactionFragment extends Fragment implements ICallback, ICallbackEMV {

    private ProgressDialog progressDialog;
    private EMVTransaction emvTransaction;
    private Handler handler = new Handler();
    private String deviceDisplayName, message, log;
    private TextView statusBar, lcdMessage, textLog, textClear;
    private ArrayList<String> devices = new ArrayList<>();
    private AlertDialog.Builder builderSingle;
    private Runnable doUpdateUI;
    private String alertTitle = "";

    public View onCreateView(@NonNull LayoutInflater inflater,
                             ViewGroup container, Bundle savedInstanceState) {

        View root = inflater.inflate(R.layout.fragment_emv_transaction, container, false);

        try {
            emvTransaction = new EMVTransaction(MainActivity.restServiceClient, this, getActivity(), ReaderInfo.DEVICE_TYPE.DEVICE_VP3300_BT);
            emvTransaction.restServiceClient.setCallback(this);
        } catch (Exception ex) {
            Toast.makeText(getActivity(), ex.getMessage(), Toast.LENGTH_LONG).show();
        }
        builderSingle = new AlertDialog.Builder(Objects.requireNonNull(getContext()));
        setOnClickListeners(root);
        return root;
    }

    private void setOnClickListeners(View view) {

        statusBar = view.findViewById(R.id.statusBar);
        lcdMessage = view.findViewById(R.id.lcdMessage);
        textLog = view.findViewById(R.id.textLog);
        textLog.setMovementMethod(new ScrollingMovementMethod());
        textClear = view.findViewById(R.id.txtClear);

        textClear.setOnClickListener(new Button.OnClickListener() {
            public void onClick(View v) {
                lcdMessage.setText("");
                textLog.setText("");
                emvTransaction.clearLog();
            }
        });

        Button btnScanDevices = view.findViewById(R.id.btnScanForBLEDevices);
        btnScanDevices.setOnClickListener(new Button.OnClickListener() {
            @Override
            public void onClick(View v) {
                devices.clear();
                progressDialog = ProgressDialog.show(getContext(), "", "Searching. Please wait..", true);
//              An alternate way to perform search for devices with device name substring and/or time out of device scan duration.
//              emvTransaction.scanForDevices("IDTECH-VP3300", 7000);
//              emvTransaction.scanForDevices(5000);
                Thread thread = new Thread() {
                    @Override
                    public void run() {
                        emvTransaction.scanForDevices();
                    }
                };
                thread.start();
            }
        });

        Button btnInitialDeviceSetup = view.findViewById(R.id.btnInitialDeviceSetup);
        btnInitialDeviceSetup.setOnClickListener(new Button.OnClickListener() {
            public void onClick(View v) {
                Thread thread = new Thread() {
                    @Override
                    public void run() {
                        emvTransaction.runInitialDeviceSetup();
                    }
                };
                thread.start();
            }
        });

        Button btnStartEMV = view.findViewById(R.id.btnStartEMV);
        btnStartEMV.setOnClickListener(new Button.OnClickListener() {
            public void onClick(View v) {
                emvTransaction.performEMVSale(transactionAction, payload);
            }
        });

        Button btnCancelEMV = view.findViewById(R.id.btnCancelEMV);
        btnCancelEMV.setOnClickListener(new Button.OnClickListener() {
            public void onClick(View v) {
                emvTransaction.cancelEMVSale();
            }
        });

        Button btnStartSwipe = view.findViewById(R.id.btnStartSwipe);
        btnStartSwipe.setOnClickListener(new Button.OnClickListener() {
            public void onClick(View v) {
                //emvTransaction.performMSRSale(transactionAction, payload);
            }
        });

        Button btnCancelSwipe = view.findViewById(R.id.btnCancelSwipe);
        btnCancelSwipe.setOnClickListener(new Button.OnClickListener() {
            public void onClick(View v) {
                //emvTransaction.cancelMSRSale();
            }
        });
    }

    private void updateAvailableBluetoothDeviceList() {
        final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(Objects.requireNonNull(getContext()), android.R.layout.select_dialog_singlechoice);
        if (devices.size() > 0) {
            for (String device : devices) {
                arrayAdapter.add(device);
            }
        } else {
            builderSingle.setMessage("No device is available to connect. Please check your device's bluetooth connection.");
            progressDialog.hide();
        }
    }

    private void showAvailableBluetoothDevice() {

        progressDialog.create();
        builderSingle = new AlertDialog.Builder(Objects.requireNonNull(getContext()));
        builderSingle.setIcon(R.drawable.zeamster_logo);
        builderSingle.setTitle("Available bluetooth devices to connect:");

        final ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(Objects.requireNonNull(getContext()), android.R.layout.select_dialog_singlechoice);
        if (devices.size() > 0) {
            for (String device : devices) {
                arrayAdapter.add(device);
            }
        } else {
            builderSingle.setMessage("No device is available to connect. Please check your device's bluetooth connection.");
            progressDialog.dismiss();
        }

        builderSingle.setNegativeButton("cancel", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                dialog.cancel();
            }
        });

        builderSingle.setAdapter(arrayAdapter, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                if (devices.size() > 0) {
                    final String name = arrayAdapter.getItem(which);
                    AlertDialog.Builder builderInner = new AlertDialog.Builder(Objects.requireNonNull(getContext()));
                    builderInner.setMessage(name);
                    builderInner.setTitle("Connecting with..");
                    builderInner.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.cancel();
                            deviceDisplayName = name;
                            updateStatusBar("Connecting..  " + deviceDisplayName, Color.BLACK, Color.YELLOW);
                            Thread thread = new Thread() {
                                @Override
                                public void run() {
                                    emvTransaction.connectDeviceByName(name);
                                }
                            };
                            thread.start();
                        }
                    });
                    builderInner.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.cancel();
                        }
                    });
                    builderInner.show();
                    progressDialog.dismiss();
                }
            }
        });
        builderSingle.show();
        progressDialog.dismiss();
    }

    private Runnable doUpdateStatus = new Runnable() {
        public void run() {
            lcdMessage.setText(message);
            textLog.setText(log);
        }
    };

    private void updateStatusBar(final String message, final int textColor, final int bgColor) {
        doUpdateUI = new Runnable() {
            public void run() {
                statusBar.setText(message);
                statusBar.setTextColor(textColor);
                statusBar.setBackgroundColor(bgColor);
            }
        };
        handler.post(doUpdateUI);
    }

    @Override
    public void deviceScanResponse(String deviceId, String deviceName) {
        if (deviceName != null && !deviceName.isEmpty()) {
            this.devices.add(deviceName);
        } else if (deviceId != null) {
            this.devices.add(deviceId);
        }
//        leaving next line for future, as per need
//        updateAvailableBluetoothDeviceList();
    }

    @Override
    public void deviceScanCompleted() {
        doUpdateUI = new Runnable() {
            public void run() {
                showAvailableBluetoothDevice();
            }
        };
        handler.post(doUpdateUI);
    }

    @Override
    public void deviceConnected(String status) {
        updateStatusBar(status, Color.WHITE, Color.GREEN);
        progressDialog.dismiss();
    }

    @Override
    public void deviceDisconnected(String status) {
        updateStatusBar(status, Color.WHITE, Color.RED);
        progressDialog.dismiss();
    }

    @Override
    public void deviceMessage(final String message) {
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                lcdMessage.setText(message);
            }
        });
    }

    @Override
    public void outputLogs(final String log) {
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                String text = textLog.getText() + log;
                textLog.setText(text);
            }
        });
    }

    @Override
    public void onSuccess(String response) {
        MainActivity.apiResponse = response;
        alertTitle = "Success";
        showResult();
    }

    @Override
    public void onFailure(String response) {
        MainActivity.apiResponse = response;
        alertTitle = "Failure!";
        showResult();
    }

    private void showResult() {
        final AlertDialog.Builder alert = new AlertDialog.Builder(getActivity());
        alert.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                MainActivity.apiResponse = "";
                alertTitle = "";
            }
        });
        String message;
        try {
            JSONObject jsonObject = new JSONObject(MainActivity.apiResponse);
            message = jsonObject.toString(2);
        } catch (JSONException ex) {
            message = ex.getMessage();
            alertTitle = "Error!";
        }
        alert.setTitle(alertTitle);
        alert.setMessage(message);
        alert.show();
    }
}