package kz.com.aman.kassa.bank;

import android.app.AlertDialog;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

import kz.com.aman.kassa.bank.gui.CustomKeyBoardDilalog;
import ru.m4bank.mpos.library.external.transactions.EasyCardRefundCallbackHandler;
import ru.m4bank.mpos.library.external.transactions.GetTransactionsListCallbackHandler;
import ru.m4bank.mpos.service.data.FiscalStatusData;
import ru.m4bank.mpos.service.data.PrinterBaseData;
import ru.m4bank.mpos.service.data.PrinterErrorData;
import ru.m4bank.mpos.service.data.dynamic.objects.Reader;
import ru.m4bank.mpos.service.data.dynamic.objects.Transaction;
import ru.m4bank.mpos.service.data.dynamic.objects.result.ResultCode;
import ru.m4bank.mpos.service.data.dynamic.objects.transaction.RefundType;
import ru.m4bank.mpos.service.hardware.error.AllError;
import ru.m4bank.mpos.service.hardware.error.ErrorHandler;
import ru.m4bank.mpos.service.hardware.external.cardreaderlib.data.ApplicationIdConv;
import ru.m4bank.mpos.service.hardware.external.cardreaderlib.data.enums.VirtualKeyboardStyleTypeConv;
import ru.m4bank.mpos.service.result.PrinterResult;
import ru.m4bank.mpos.service.result.Result;
import ru.m4bank.mpos.service.transactions.data.ButtonKeyboardDto;
import ru.m4bank.mpos.service.transactions.data.MessageButtonData;
import ru.m4bank.mpos.service.transactions.data.TransactionData;
import ru.m4bank.mpos.service.transactions.data.TransactionExecutionStatus;
import ru.m4bank.mpos.service.transactions.data.error.TransactionErrorData;
import ru.m4bank.mpos.service.transactions.dto.OnlineCardDataDto;
import timber.log.Timber;

public class CardRefundCallbackHandlerImpl implements EasyCardRefundCallbackHandler<Result>, GetTransactionsListCallbackHandler<Result> {

    private final M4BankActivity activity;
    private Transaction transaction;
    private CustomKeyBoardDilalog customKeyBoardDilalog;

    public CardRefundCallbackHandlerImpl(M4BankActivity activity) {
        this.activity = activity;
        customKeyBoardDilalog = new CustomKeyBoardDilalog();
    }

    @Override
    public void onCardReaderForTransactionGettingCompleted() {
        Timber.d("Reader has been received");
    }

    @Override
    public void onNoBoundedDevicesFound() {
        Timber.d("No bounded readers");
    }

    @Override
    public void onDeviceToUseSelectionRequested(List<Reader> deviceList) {
        Timber.d("onDeviceToUseSelectionRequested");
        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
        builder.setTitle("Choose device");

        Spinner deviceListSpinner = new Spinner(activity);
        ArrayAdapter<Reader> adapter = new ArrayAdapter<>(activity, android.R.layout.simple_spinner_item, new ArrayList<>(deviceList));
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        deviceListSpinner.setAdapter(adapter);

        builder.setPositiveButton("OK", (dialog, which) -> {
            activity.getClientInterface().getTransactionManager().setCardReaderToUse((Reader) deviceListSpinner.getSelectedItem());
            dialog.dismiss();
        });

        builder.setView(deviceListSpinner);
        activity.runOnUiThread(() -> builder.create().show());
    }

    @Override
    public void onDeviceToConnectSelectionRequested(List<String> deviceList) {
        Timber.d("onDeviceToConnectSelectionRequested");
        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
        builder.setTitle("Choose device");

        Spinner deviceListSpinner = new Spinner(activity);
        ArrayAdapter<String> adapter = new ArrayAdapter<>(activity, android.R.layout.simple_spinner_item, deviceList);
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        deviceListSpinner.setAdapter(adapter);

        builder.setPositiveButton("OK", (dialog, which) -> {
            activity.getClientInterface().getTransactionManager().selectCardReader(deviceListSpinner.getSelectedItem().toString());
            dialog.dismiss();
        });

        builder.setView(deviceListSpinner);
        activity.runOnUiThread(() -> builder.create().show());
    }

    @Override
    public void onCompleted(Result result) {
        Timber.d("onCompleted");
        activity.runOnUiThread(() -> Toast.makeText(activity, result.getResultType() + " " + (result.getDescription() == null ? "" : result.getDescription()),
                Toast.LENGTH_SHORT).show());
    }

    @Override
    public void onWrongApiCalled() {
        Timber.d("onWrongApiCalled");
        activity.runOnUiThread(() -> Toast.makeText(activity, "Wrong method has been called", Toast.LENGTH_SHORT).show());
    }

    @Override
    public void onReceiveCardData(OnlineCardDataDto data, boolean shouldConfirmBeManuallyCalled) {
        Timber.d("onReceiveCardData");
        if (shouldConfirmBeManuallyCalled) {
            activity.getClientInterface().getTransactionManager().processOnlineTransaction(false);
        }
    }

    @Override
    public void onRequiredReversal(String description, ResultCode resultCode) {
        Timber.d("onRequiredReversal: %s, resultCode: %s", description, resultCode.name());
    }

    @Override
    public void onRequiredApplicationSelection(List<ApplicationIdConv> list) {
        Timber.d("onRequiredApplicationSelection");
    }

    @Override
    public void onTransactionInit() {

    }

    @Override
    public void onTransactionExecutionStatusChanged(TransactionExecutionStatus newStatus) {
        Timber.d("onTransactionExecutionStatusChanged: %s", newStatus.name());
        activity.runOnUiThread(() -> Toast.makeText(activity, newStatus.name(), Toast.LENGTH_SHORT).show());
    }

    @Override
    public void onError(ErrorHandler errorHandler, TransactionErrorData transactionErrorData) {
        Timber.d("onError: %s, description: %s", ((AllError) errorHandler).name(), errorHandler.getDescription());
        activity.runOnUiThread(() -> Toast.makeText(activity, errorHandler.getFinalDescription(), Toast.LENGTH_LONG).show());
    }

    @Override
    public void onErrorWithPossibilityToRetry(ErrorHandler errorHandler) {
        Timber.d("onErrorWithPossibilityToRetry: %s, description: %s", ((AllError) errorHandler).name(), errorHandler.getDescription());
        activity.runOnUiThread(() -> Toast.makeText(activity, errorHandler.getFinalDescription(), Toast.LENGTH_LONG).show());
        activity.getClientInterface().getTransactionManager().tryToRepeatExecuteLastRequestInTransaction();
    }

    @Override
    public void onTransactionDataReceivedError(TransactionData data) {
        Timber.d("onTransactionDataReceivedError");
    }

    @Override
    public void onUserInformationRequested(boolean signNeeded) {
        Timber.d("onUserInformationRequested");
        activity.getClientInterface().getTransactionManager().sendTransactionUserData("signature", "phone", "email");
    }

    @Override
    public void onTransactionDataReceived(TransactionData data) {
        Timber.d("onTransactionDataReceived");
        activity.runOnUiThread(() -> Toast.makeText(activity, "Transaction data has been received", Toast.LENGTH_LONG)
                .show());
    }

    @Override
    public void onTransactionCompleted() {
        Timber.d("onTransactionCompleted");
        activity.runOnUiThread(() -> Toast.makeText(activity, "Operation has been successfully completed", Toast.LENGTH_LONG)
                .show());
    }

    @Override
    public void onDisconnectedEventReceivedOrCanNotEstablishConnection(boolean reconnectAvailable, String description) {
        Timber.d("onDisconnectedEventReceivedOrCanNotEstablishConnection");
    }

    @Override
    public void onConnectingProcessStarted(String name) {
        Timber.d("onConnectingProcessStarted: %s", name);
    }

    @Override
    public void onReconnectNeededToProcess() {
        Timber.d("onReconnectNeededToProcess");
    }

    @Override
    public void onReconciliationRequiredToProcess() {
        Timber.d("onReconciliationRequiredToProcess");
        Timber.d("Reconciliation required!!!");
        activity.getClientInterface().getTransactionManager().makeReconciliationDuringTransaction();
    }

    @Override
    public void onReconciliationCompleted(Result result) {
        Timber.d("onReconciliationCompleted");
        Timber.d("Reconciliation completed!!!");
    }

    @Override
    public void notAuthorized() {
        Timber.d("notAuthorized");
        activity.runOnUiThread(() -> Toast.makeText(activity, "notAuthorized", Toast.LENGTH_SHORT).show());
    }

    @Override
    public void onRepeat(int attemptNumber) {
        Timber.d("onRepeat");
        activity.runOnUiThread(() -> Toast.makeText(activity, "Repeat attempt number " + attemptNumber, Toast.LENGTH_SHORT).show());
    }

    @Override
    public void onRequestedReportZ() {
        Timber.d("onRequestedReportZ");
    }

    @Override
    public void onCompletedPrinting(PrinterResult<PrinterErrorData, PrinterBaseData> printerErrorDataPrinterBaseDataPrinterResult) {
        Timber.d("onCompletedPrinting");
    }

    @Override
    public void onStatusFiscalModule(FiscalStatusData fiscalStatusData) {
        Timber.d("onStatusFiscalModule");
    }

    @Override
    public void onPrinterForRegistrationGettingCompleted() {
        Timber.d("onPrinterForRegistrationGettingCompleted");
    }

    @Override
    public void onNoBoundedPrinterFound() {
        Timber.d("onNoBoundedPrinterFound");
    }

    @Override
    public void onPrinterToUseSelectionRequested(List<String> printerList) {
        Timber.d("onPrinterToUseSelectionRequested");
    }

    @Override
    public void onRefundDataRequested() {
        Timber.d("onRefundDataRequested");
        activity.getClientInterface().getTransactionManager().setRefundData(transaction, transaction.getAmount(), RefundType.General);
    }

    @Override
    public void onTransactionsListReceived(List<Transaction> transactionList) {
        Timber.d("onTransactionsListReceived");
        AlertDialog.Builder builder = new AlertDialog.Builder(activity);
        builder.setTitle("Choose transaction");

        Spinner transactionListSpinner = new Spinner(activity);
        ArrayAdapter<Transaction> adapter = new ArrayAdapter<>(activity, android.R.layout.simple_spinner_item, new ArrayList<>(transactionList));
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        transactionListSpinner.setAdapter(adapter);

        builder.setPositiveButton("OK", (dialog, which) -> {
            transaction = (Transaction) transactionListSpinner.getSelectedItem();
            activity.getClientInterface().getTransactionManager().makeCardRefund(this);
            dialog.dismiss();
        });

        builder.setView(transactionListSpinner);
        activity.runOnUiThread(() -> builder.create().show());
    }

    @Override
    public void onActivityUpdateUiThread() {
        Timber.d("onActivityUpdateUiThread");
        activity.getClientInterface().getTransactionManager().addPinpadClickListener(activity);
    }

    @Override
    public void onCreatePinPadButtons() {
        Timber.d("onCreatePinPadButtons");
        customKeyBoardDilalog.createDialog(activity);
        customKeyBoardDilalog.show(activity);
        ButtonKeyboardDto buttonKeyboardDto = new ButtonKeyboardDto.Build(
                customKeyBoardDilalog.getBtnb1(),
                customKeyBoardDilalog.getBtnb2(),
                customKeyBoardDilalog.getBtnb3(),
                customKeyBoardDilalog.getBtnb4(),
                customKeyBoardDilalog.getBtnb5(),
                customKeyBoardDilalog.getBtnb6(),
                customKeyBoardDilalog.getBtnb7(),
                customKeyBoardDilalog.getBtnb8(),
                customKeyBoardDilalog.getBtnb9(),
                customKeyBoardDilalog.getBtnb0(),
                customKeyBoardDilalog.getBtncancel(),
                customKeyBoardDilalog.getBtnconfirm(),
                customKeyBoardDilalog.getBtnclean(),
                activity.getWindowManager().getDefaultDisplay().getRotation()
        ).build();
        activity.getClientInterface().getTransactionManager().addPinPadButtons(buttonKeyboardDto);
    }

    @Override
    public void onShowPinPadKeyBoard(MessageButtonData messageButtonData) {
        Timber.d("onShowPinPadKeyBoard");
        customKeyBoardDilalog.setText(messageButtonData);
    }

    @Override
    public void onUpdateElementPin(int count) {
        Timber.d("onUpdateElementPin");
        activity.runOnUiThread(() -> Toast.makeText(activity, "count = " + count, Toast.LENGTH_SHORT).show());
    }

    @Override
    public void onCloseKeyboard() {
        Timber.d("onCloseKeyboard");
        customKeyBoardDilalog.close(activity);
    }

    @Override
    public void onRequiredAdditionalVirtualKeyboardSettings(VirtualKeyboardStyleTypeConv virtualKeyboardStyleTypeConv) {
        activity.showSelectStyleDialog(additionalData ->
                activity.getClientInterface().getTransactionManager().addVirtualPinKeyboardData(additionalData));
    }

    @Override
    public void onRequiredHostAddress() {
        Timber.d("onRequiredHostAddress");
        activity.runOnUiThread(() -> Toast.makeText(activity, "Set Host Address", Toast.LENGTH_LONG)
                .show());
        activity.getClientInterface().getTransactionManager().setHostAddress("213.79.122.128", "8011");
    }
}
