package kz.com.aman.kassa.plugins;

import android.os.Build;
import android.widget.Toast;

import com.google.gson.Gson;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import kz.com.aman.kassa.MainActivity;
import kz.com.aman.kassa.bank.DeviceTypeDefiner;
import kz.com.aman.kassa.bank.SessionExpiringCallbackHandlerImpl;
import kz.com.aman.kassa.bank.builders.SslConfigurationBuilder;
import kz.com.aman.kassa.bank.permissions.PermissionsManager;
import kz.com.aman.kassa.bank.permissions.PermissionsManagerImpl;
import kz.com.aman.kassa.handler.AuthorizationHandlerImpl;
import kz.com.aman.kassa.handler.CardPaymentHandlerImpl;
import kz.com.aman.kassa.handler.ConnectionCheckHandlerImpl;
import kz.com.aman.kassa.handler.TransactionDetailsHandlerImpl;
import kz.com.aman.kassa.model.AmanDao;
import ru.m4bank.mpos.library.M4BankMposClient;
import ru.m4bank.mpos.library.M4BankMposClientInterfaceFacade;
import ru.m4bank.mpos.library.M4BankMposParameters;
import ru.m4bank.mpos.library.external.authorization.AuthorizationCallbackHandler;
import ru.m4bank.mpos.library.external.transactions.GetTransactionsListCallbackHandler;
import ru.m4bank.mpos.service.authorization.network.AuthorizationResponse;
import ru.m4bank.mpos.service.commons.data.ConfigurationSettings;
import ru.m4bank.mpos.service.commons.data.NetworkConfiguration;
import ru.m4bank.mpos.service.commons.data.TerminalConfiguration;
import ru.m4bank.mpos.service.data.dynamic.CurrencyDataHolder;
import ru.m4bank.mpos.service.data.dynamic.objects.Currency;
import ru.m4bank.mpos.service.data.dynamic.objects.GetOperationType;
import ru.m4bank.mpos.service.hardware.external.cardreaderlib.data.enums.TransactionTypeConv;
import ru.m4bank.mpos.service.network.Format;
import ru.m4bank.mpos.service.network.ServerChoose;


public class BankNfcPlugins implements MethodCallHandler {

    private final Gson gson = new Gson();

    //main activity
    private MainActivity activity;

    //main client all work with him
    private M4BankMposClientInterfaceFacade clientInterface;
    //permissions
    private PermissionsManager permissionsManager;

    public M4BankMposClientInterfaceFacade getClientInterface() {
        return this.clientInterface;
    }

    public MainActivity getActivity() {
        return this.activity;
    }

    public BankNfcPlugins(MainActivity activity) {
        this.activity = activity;
    }

    @Override
    public void onMethodCall(MethodCall call, Result result) {
        switch (call.method) {
            case "init":
                init(call, result);
                break;
            case "permissions":
                permissions(result);
                break;
            case "connection":
                connection(result);
                break;
            case "currency":
                currency(result);
                break;
            case "auth":
                authentication(call, result);
                break;
            case "pay":
                pay(call, result);
                break;
            case "cancel":
                cancel(call, result);
                break;
            case "shutdown":
                shutdown(call, result);
                break;
            case "transaction":
                showTransaction(call, result);
                break;
            case "version":
                result.success(String.valueOf(Build.VERSION.SDK_INT));
                break;
            case "get":
                AmanDao<String> dao = new AmanDao<>();
                dao.setSuccess(true);
                dao.setMsg("Hello World");
                result.success(gson.toJson(dao));
                break;
            case "error":
                result.error("0-code","0-message", "0-details");
                break;
            default:
                result.notImplemented();
        }
    }


    private static int getVersion() {
        String version = System.getProperty("java.version");
        if(version.startsWith("1.")) {
            version = version.substring(2, 3);
        } else {
            int dot = version.indexOf(".");
            if(dot != -1) { version = version.substring(0, dot); }
        } return Integer.parseInt(version);
    }

    private void permissions(Result result) {
        try {
            PermissionsManager.PermissionsCheckResultHandler permissionsCheckResultHandler =
                    new PermissionsManager.PermissionsCheckResultHandler() {
                        @Override
                        public void onPermissionsGranted() {
                            activity.runOnUiThread(() -> {
                                        AmanDao<String> dao = new AmanDao<>();
                                        dao.setSuccess(true);
                                        dao.setMsg("OK");
                                        result.success(gson.toJson(dao));
                                    }
                            );

                        }

                        @Override
                        public void onPermissionsDeclined() {
                            AmanDao<String> dao = new AmanDao<>();
                            dao.setSuccess(false);
                            dao.setMsg("decline");
                            result.success(gson.toJson(dao));
                        }
                    };
            permissionsManager = new PermissionsManagerImpl(this.activity);
            permissionsManager.checkPermissions(permissionsCheckResultHandler);


        } catch (Exception e) {
            result.error("1", e.getMessage(), e.getLocalizedMessage());
        }
    }


    private void init(MethodCall call, Result result) {
        String serverUrl = call.argument("serverUrl");
        start(serverUrl);
        AmanDao<String> dao = new AmanDao<>();
        dao.setSuccess(true);
        dao.setMsg("OK");
        result.success(gson.toJson(dao));

    }

    //start after all permissions granted
    private void start(String serverUrl) {
        clientInterface = M4BankMposClient.getInstance(
                new M4BankMposParameters(
                        Format.JSON,
                        "rus",
                        null,
                        this.activity,
                        new SessionExpiringCallbackHandlerImpl(),
                        "appName",
                        ServerChoose.API_5_0,
                        new ConfigurationSettings
                                .Builder()
                                .printerUsed(true)
                                .umkaEnabled(true)
                                .networkConfiguration(createNetworkConfiguration(serverUrl))
                                .terminalConfiguration(createTerminalConfiguration())
                                .build())
        );
    }

    private void connection(Result result) {
        clientInterface.getConfigurationManager()
                .checkConnection(
                        new ConnectionCheckHandlerImpl(this.activity, result));
    }
    private void currency(Result result) {
        CurrencyDataHolder dataHolder = clientInterface.getConfigurationManager()
                .getCurrencyDataHolder();
        Currency currentCurrency = dataHolder.getCurrency();
        if(currentCurrency!=null){
            System.out.println(currentCurrency.getName());
            System.out.println(currentCurrency.getCurrency3DigitCode());
        } else {
            System.out.println("currentCurrency is null");
        }
        System.out.println("===========================");
        if(currentCurrency == null || !"398".equalsIgnoreCase(currentCurrency.getCurrency3DigitCode()) ){
            List<Currency> currencies = dataHolder.getCurrencyList();
            boolean changed = false;
            for(Currency currency : currencies ){
                System.out.println(currency.getName());
                System.out.println(currency.getLetterCode());
                System.out.println(currency.getCurrency3DigitCode());
                if("398".equalsIgnoreCase(currency.getCurrency3DigitCode())){
                    dataHolder.setCurrency(currency);
                    changed = true;
                    break;
                }
            }
            AmanDao<String> dao = new AmanDao<>();
            dao.setSuccess(changed);
            dao.setMsg("current currency " + (currentCurrency!=null ? currentCurrency.getLetterCode() : "NULL"));
            result.success(gson.toJson(dao));
        } else {
            AmanDao<String> dao = new AmanDao<>();
            dao.setSuccess(true);
            dao.setMsg("exist");
            result.success(gson.toJson(dao));
        }
    }



    private void authentication(MethodCall call, Result result) {
        String login = call.argument("login");
        String password = call.argument("password");
        clientInterface.getAuthorizationManager().authorize(new AuthorizationHandlerImpl(this, result,  login, password) );
    }

    private void pay(MethodCall call, Result result) {
        try {
            Integer value = call.argument("amount");
            long amount = value.longValue();
            clientInterface.cancel();
//            CardPaymentHandlerImpl handler = new CardPaymentHandlerImpl(this, result, amount);
//            handler.setTransactionTypeConv(TransactionTypeConv.PAYMENT);
//            clientInterface.getTransactionManager().makeCardPayment(handler);
            clientInterface.getTransactionManager().makeCardPayment(new CardPaymentHandlerImpl(this, result, amount, TransactionTypeConv.PAYMENT));
        } catch (Exception e) {
            System.out.println("=============>ERROR:"+e.getMessage());
            result.error("2", e.getMessage(), e.getLocalizedMessage());
        }
    }

    private void showTransaction(MethodCall call, Result result){
        clientInterface.getTransactionManager()
                .getTransactionsList(
                        new TransactionDetailsHandlerImpl(this),
                        20, 0,
                        GetOperationType.SHOW,
                        null);
    }

    private void cancel(MethodCall call, Result result) {
        try {
            clientInterface.cancel();
            AmanDao<String> dao = new AmanDao<>();
            dao.setSuccess(true);
            dao.setMsg("OK");
            result.success(gson.toJson(dao));
        } catch (Exception e) {
            System.out.println("=============>ERROR:"+e.getMessage());
            result.error("2", e.getMessage(), e.getLocalizedMessage());
        }
    }

    private void shutdown(MethodCall call, Result result) {
        try {
            clientInterface.shutdown();
            AmanDao<String> dao = new AmanDao<>();
            dao.setSuccess(true);
            dao.setMsg("OK");
            result.success(gson.toJson(dao));
        } catch (Exception e) {
            System.out.println("=============>ERROR:"+e.getMessage());
            result.error("2", e.getMessage(), e.getLocalizedMessage());
        }
    }

    //terminal config
    private TerminalConfiguration createTerminalConfiguration() {
        System.out.println("=============>createTerminalConfiguration:"+new DeviceTypeDefiner().define());
        return new TerminalConfiguration.Builder()
                .energySaverModeTime(150)
                .pinLengthsArray(new byte[]{4, 6})
                .shutDownModeTime(300)
                .deviceType(new DeviceTypeDefiner().define())
                .build();
    }

    //network config
    private NetworkConfiguration createNetworkConfiguration(String serverUrl) {
        return new NetworkConfiguration.Builder()
                .sslConfiguration(SslConfigurationBuilder.buildAllTrustConfiguration(serverUrl))
                .serverUrl(serverUrl)
                .build();
    }


}