package kz.com.aman.kassa.bank;

import android.app.AlertDialog;
import android.graphics.BitmapFactory;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.text.format.Formatter;
import android.view.View;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Toast;

import androidx.annotation.NonNull;

import org.slf4j.LoggerFactory;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.android.LogcatAppender;
import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
import io.flutter.app.FlutterActivity;
import kz.com.aman.kassa.R;
import kz.com.aman.kassa.bank.builders.SslConfigurationBuilder;
import kz.com.aman.kassa.bank.gui.SelectDialogCallback;
import kz.com.aman.kassa.bank.gui.SelectElementDialog;
import kz.com.aman.kassa.bank.managing.PreferencesManager;
import kz.com.aman.kassa.bank.permissions.PermissionsManager;
import kz.com.aman.kassa.bank.permissions.PermissionsManagerImpl;
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.ActivationCallbackHandler;
import ru.m4bank.mpos.library.external.authorization.AuthorizationCallbackHandler;
import ru.m4bank.mpos.library.external.authorization.GetMerchantUsersCallbackHandler;
import ru.m4bank.mpos.library.external.authorization.LogOutCallbackHandler;
import ru.m4bank.mpos.library.external.configuration.CheckConnectionCallbackHandler;
import ru.m4bank.mpos.library.external.configuration.GetLicenseCallbackHandler;
import ru.m4bank.mpos.library.external.transactions.CardReadingCallbackHandler;
import ru.m4bank.mpos.library.external.transactions.CashPaymentCallbackHandler;
import ru.m4bank.mpos.library.external.transactions.EasyCardRefundCallbackHandler;
import ru.m4bank.mpos.library.external.transactions.EasyCashRefundCallbackHandler;
import ru.m4bank.mpos.library.external.transactions.EasyReversalSavedOperationCallbackHandler;
import ru.m4bank.mpos.library.external.transactions.GetCardReaderInformationCallbackHandler;
import ru.m4bank.mpos.library.external.transactions.GetTransactionDetailsCallbackHandler;
import ru.m4bank.mpos.library.external.transactions.GetTransactionsListCallbackHandler;
import ru.m4bank.mpos.library.external.transactions.LastReversalCardPaymentCallbackHandler;
import ru.m4bank.mpos.library.external.transactions.ResendReceiptCallbackHandler;
import ru.m4bank.mpos.library.external.transactions.ReversalCallbackHandler;
import ru.m4bank.mpos.library.external.transactions.ScanBarCodeCallbackHandler;
import ru.m4bank.mpos.library.external.transactions.XReportCallbackHandler;
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.configuration.data.RegisterRequestData;
import ru.m4bank.mpos.service.data.dictionary.DictionaryCore;
import ru.m4bank.mpos.service.data.dictionary.LanguageCore;
import ru.m4bank.mpos.service.data.dictionary.MessageCore;
import ru.m4bank.mpos.service.data.dynamic.objects.GetOperationType;
import ru.m4bank.mpos.service.data.dynamic.objects.OperationType;
import ru.m4bank.mpos.service.data.dynamic.objects.PIDataType;
import ru.m4bank.mpos.service.data.dynamic.objects.ScanBarCodeScreenDataInput;
import ru.m4bank.mpos.service.data.dynamic.objects.TransactionFilterData;
import ru.m4bank.mpos.service.hardware.external.cardreaderlib.data.enums.TransactionTypeConv;
import ru.m4bank.mpos.service.hardware.network.external.TerminalKeyType;
import ru.m4bank.mpos.service.hardware.printer.dto.data.PrinterSeries;
import ru.m4bank.mpos.service.hardware.printer.dto.data.PrintingType;
import ru.m4bank.mpos.service.hardware.printer.dto.data.enums.SlipType;
import ru.m4bank.mpos.service.hardware.printer.dto.template.Align;
import ru.m4bank.mpos.service.hardware.printer.dto.template.BarcodeCheckObject;
import ru.m4bank.mpos.service.hardware.printer.dto.template.ImageCheckObject;
import ru.m4bank.mpos.service.hardware.printer.dto.template.PrintingTemplate;
import ru.m4bank.mpos.service.hardware.printer.dto.template.QRCodeCheckObject;
import ru.m4bank.mpos.service.hardware.printer.dto.template.StringCheckObject;
import ru.m4bank.mpos.service.hardware.printer.dto.template.StringSpan;
import ru.m4bank.mpos.service.hardware.printer.dto.template.TextStyle;
import ru.m4bank.mpos.service.network.Format;
import ru.m4bank.mpos.service.network.ServerChoose;
import ru.m4bank.mpos.service.transactions.data.VirtualPinKeyboardData;
import ru.m4bank.mpos.service.transactions.data.external.ExternalTemplateData;
import timber.log.Timber;


public class M4BankActivity extends FlutterActivity {
    private M4BankMposClientInterfaceFacade clientInterface;

    private AuthorizationCallbackHandler authorizationCallbackHandler;
    private LogOutCallbackHandler logOutCallbackHandler;
    private CheckConnectionCallbackHandler checkConnectionCallbackHandler;
    private CardPaymentCallbackHandlerImpl cardPaymentCallbackHandler;
    private CardReadingCallbackHandler cardReadingCallbackHandler;
    private CashPaymentCallbackHandler cashPaymentCallbackHandler;
    private AlipayPaymentCallbackHandlerImpl alipayPaymentCallbackHandler;
    private EcomPaymentCallbackHandlerImpl ecomPaymentCallbackHandler;
    private EasyCardRefundCallbackHandler cardRefundCallbackHandler;
    private EasyCashRefundCallbackHandler easyCashRefundCallbackHandler;
    private EasyAlipayRefundCallbackHandlerImpl easyAlipayRefundCallbackHandler;
    private EasyEcomRefundCallbackHandlerImpl easyEcomRefundCallbackHandler;
    private ReversalCallbackHandler easyReversalCallbackHandler;
    private GetMerchantUsersCallbackHandler getMerchantUsersCallbackHandler;
    private ActivationCallbackHandler activationCallbackHandler;
    private GetLicenseCallbackHandler getLicenseCallbackHandler;
    private ResendReceiptCallbackHandler resendReceiptCallbackHandler;
    private GetTransactionDetailsCallbackHandler getTransactionDetailsCallbackHandler;
    private PrintingCallbackHandlerImpl printingCallbackHandler;
    private XReportCallbackHandler xReportCallbackHandler;
    private LastReversalCardPaymentCallbackHandler revertCurrentOperationCallbackHandler;
    private GetCardReaderInformationCallbackHandler getCardReaderInformationCallbackHandler;
    private EasyReversalSavedOperationCallbackHandler easyReversalSavedOperationCallbackHandler;

    private GetTransactionListForRefundCallbackHandlerImpl getTransactionListForRefundCallbackHandler;
    private SendRegisterRequestCallbackHandlerImpl sendRegisterRequestCallbackHandler;
    private EasyCardReversalCallbackHandlerImpl easyCardReversalCallbackHandler;
    private CloseDayCallbackHandlerImpl closeDayCallbackHandler;
    private LoadTerminalKeysCallbackHandlerImpl loadTerminalKeysCallbackHandler;
    private ScanBarCodeCallbackHandler scanBarCodeCallbackHandler;

    public M4BankMposClientInterfaceFacade getClientInterface() {
        return clientInterface;
    }

    private LogcatAppender appender;

    private String login;
    private String password;

    private PermissionsManager permissionsManager;

    public String getLogin() {
        return login;
    }

    public String getPassword() {
        return password;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Timber.plant(new Timber.DebugTree());
        setContentView(R.layout.activity_main);
        new Handler();
        PermissionsManager.PermissionsCheckResultHandler permissionsCheckResultHandler =
                new PermissionsManager.PermissionsCheckResultHandler() {
                    @Override
                    public void onPermissionsGranted() {
                        init();
                    }

                    @Override
                    public void onPermissionsDeclined() {
                        Toast.makeText(M4BankActivity.this,
                                "Application can work incorrectly caused by missing permissions", Toast.LENGTH_SHORT)
                                .show();
                        init();
                    }
                };
        permissionsManager = new PermissionsManagerImpl(this);
        permissionsManager.checkPermissions(permissionsCheckResultHandler);

    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[],
                                           @NonNull int[] grantResults) {
        permissionsManager.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    private void init() {
        LoggerContext lc = (LoggerContext) LoggerFactory.getILoggerFactory();
        PatternLayoutEncoder encoder = new PatternLayoutEncoder();
        encoder.setContext(lc);
        encoder.setPattern("%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n");
        encoder.start();
        appender = new LogcatAppender();
        appender.setContext(lc);
        appender.setEncoder(encoder);
        appender.start();


        //слушатель активации
        activationCallbackHandler = new ActivationCallbackHandlerImpl(this);
        //слушатель авторизации
        authorizationCallbackHandler = new AuthorizationCallbackHandlerImpl(this);
        //слушатель завершения сессии
        logOutCallbackHandler = new LogOutCallbackHandlerImpl(this);
        //слушатель проверки коннекта с сервером и получения конфигурационных данных
        checkConnectionCallbackHandler = new CheckConnectionCallbackHandlerImpl(this);
        //слушатель получения данных карты
        cardReadingCallbackHandler = new CardReadingCallbackHandlerImpl(this);

        //слушатели для оплат
        cardPaymentCallbackHandler = new CardPaymentCallbackHandlerImpl(this);
        cashPaymentCallbackHandler = new CashPaymentCallbackHandlerImpl(this);
        alipayPaymentCallbackHandler = new AlipayPaymentCallbackHandlerImpl(this);
        ecomPaymentCallbackHandler = new EcomPaymentCallbackHandlerImpl(this);

        //слушатели для возвратов
        cardRefundCallbackHandler = new CardRefundCallbackHandlerImpl(this);
        getTransactionListForRefundCallbackHandler = new GetTransactionListForRefundCallbackHandlerImpl(this,
                (CardRefundCallbackHandlerImpl) cardRefundCallbackHandler);
        easyCashRefundCallbackHandler = new EasyCashRefundCallbackHandlerImpl(this);
        easyAlipayRefundCallbackHandler = new EasyAlipayRefundCallbackHandlerImpl(this);

        //слушатели для отмен
        //слушатель для отмены карточной операции без участия ридера
        easyReversalCallbackHandler = new EasyReversalCallbackHandlerImpl(this);
        //слушатель для отмены карточной операции с участием ридера
        easyCardReversalCallbackHandler = new EasyCardReversalCallbackHandlerImpl(this);
        //слушатель для отмены текущей операции, когда данные по транзакции сохранены в кеше и не производилась очистка или новая операция
        revertCurrentOperationCallbackHandler = new RevertCurrentOperationCallbackHandlerImpl(this);

        //слушатель для записи на терминал ключей
        loadTerminalKeysCallbackHandler = new LoadTerminalKeysCallbackHandlerImpl(this);

        //слушатель для получения списка мерчантов
        getMerchantUsersCallbackHandler = new GetMerchantUsersCallbackHandlerImpl(this);
        //слушатель получения лицензии
        getLicenseCallbackHandler = new GetLicenseCallbackHandlerImpl(this);
        //слушатель повторной отправки чека
        resendReceiptCallbackHandler = new ResendReceiptCallbackHandlerImpl(this);
        //слушатель получения информации о транзакциях и детальной информации по конкретной операции
        getTransactionDetailsCallbackHandler = new GetTransactionDetailsCallbackHandlerImpl(this);
        //заявка на mpos
        sendRegisterRequestCallbackHandler = new SendRegisterRequestCallbackHandlerImpl(this);
        //слушатель закрытия опер дня и сверки с сервером
        closeDayCallbackHandler = new CloseDayCallbackHandlerImpl(this);
        //слушатели печати
        printingCallbackHandler = new PrintingCallbackHandlerImpl(this);
        //слушатель для получения серийного номера
        getCardReaderInformationCallbackHandler = new GetCardReaderInformationCallbackHandlerImpl(this);
        //слушатель для считывания barcode
        scanBarCodeCallbackHandler = new ScanBarCodeCallbackHandlerImpl(this);
        // слушатель для отмены неуспешной операции, которая сохранена в холдере
        easyReversalSavedOperationCallbackHandler = new EasyReversalSavedOperationCallbackHandlerImpl(this);

        initLoginForm();

        initButton(R.id.readerInformation, v -> getReaderInformation());

        initButton(R.id.activate, v -> clientInterface.getAuthorizationManager().activate(activationCallbackHandler));

        initButton(R.id.logout,
                v -> clientInterface.getAuthorizationManager().logOut(logOutCallbackHandler));

        initButton(R.id.checkConnection, v -> clientInterface.getConfigurationManager()
                .checkConnection(
                        checkConnectionCallbackHandler));

        initButton(R.id.checkAccess, v -> {
            String result;
            if (clientInterface.getConfigurationManager()
                    .isOperationAllowed(
                            OperationType.getByCode(((Spinner) findViewById(R.id.checkAccessSpinner))
                                    .getSelectedItem()
                                    .toString()))) {
                result = "YES";
            } else {
                result = "NO";
            }
            Toast.makeText(this, result, Toast.LENGTH_SHORT).show();
        });

        initButton(R.id.getAccesses, v -> {
            StringBuilder result = new StringBuilder();
            List<OperationType> availableOperations = clientInterface.getConfigurationManager()
                    .getAllowedOperationsList();
            if (!availableOperations.isEmpty()) {
                for (OperationType o : availableOperations) {
                    result.append(o.getCode()).append("\n");
                }
            } else {
                result.append("No available operations");
            }
            Toast.makeText(this, result.toString(), Toast.LENGTH_SHORT).show();
        });

        initButton(R.id.getAccessPaymentInstruments, v -> {
            boolean ecom = clientInterface.getConfigurationManager().isPaymentInstrumentsAllowed(PIDataType.ECOM);
            boolean alipay =
                    clientInterface.getConfigurationManager().isPaymentInstrumentsAllowed(PIDataType.ALIPAY_STANDARD);
            boolean card =
                    clientInterface.getConfigurationManager().isPaymentInstrumentsAllowed(PIDataType.CARD_STANDART);
            boolean cash = clientInterface.getConfigurationManager().isPaymentInstrumentsAllowed(PIDataType.CASH);
        });

        initButton(R.id.cancel, v -> clientInterface.cancel());

        initButton(R.id.getLicense, v -> {
            clientInterface.cancel();
            clientInterface.getConfigurationManager().getLicense(getLicenseCallbackHandler);
        });

        findViewById(R.id.getCommonCardData).setOnClickListener(v -> {
            clientInterface.cancel();
            clientInterface.getTransactionManager().getCommonCardData(cardReadingCallbackHandler);
        });

        //////////// вызовы оплат //////////////
        initButton(R.id.makeCardPayment, v -> {
            clientInterface.cancel();
            cardPaymentCallbackHandler.setTransactionTypeConv(TransactionTypeConv.PAYMENT);
            clientInterface.getTransactionManager().makeCardPayment(cardPaymentCallbackHandler);
        });

        initButton(R.id.makeCashPayment, v -> {
            clientInterface.cancel();
            clientInterface.getTransactionManager().makeCashPayment(cashPaymentCallbackHandler);
        });

        initButton(R.id.ecomPayment, v -> {
            clientInterface.cancel();
            clientInterface.getTransactionManager().makeEcomPayment(ecomPaymentCallbackHandler);
        });

        initButton(R.id.makeAlipayPayment,
                v -> clientInterface.getTransactionManager().makeAlipayPayment(alipayPaymentCallbackHandler));

        //////////// вызов подтверждения платежа и дисконнекта устройств//////////////
        initButton(R.id.completePayment,
                v -> clientInterface.getTransactionManager().completeTransaction());

        //////////// вызовы отмен - хостовые терминалы//////////////
        //////////// вызов отмены текущей транзакции с использованием слушателя оплаты (только во время транзакции)//////////////
        initButton(R.id.makeReversalLast, v -> {
            cardPaymentCallbackHandler.setTransactionTypeConv(TransactionTypeConv.CANCEL);
            clientInterface.getTransactionManager().revertCurrentOperation(revertCurrentOperationCallbackHandler);
        });

        //////////// вызов отмены текущей транзакции с использованием нового слушателя (только во время транзакции) - хостовые терминалы//////////////
        initButton(R.id.makeReversalLastWithCallback, v -> clientInterface.getTransactionManager()
                .revertCurrentOperation(
                        revertCurrentOperationCallbackHandler));

        /////////// вызовы отмены по карте//////////////
        initButton(R.id.makeEasyCardReversal, v -> {
            clientInterface.cancel();
            clientInterface.getTransactionManager()
                    .getTransactionsList(easyCardReversalCallbackHandler, 20, 0, GetOperationType.SHOW, null);
        });

        /////////// вызовы отмены на сервере//////////////
        initButton(R.id.makeEasyReversal, v -> clientInterface.getTransactionManager()
                .getTransactionsList(
                        (GetTransactionsListCallbackHandler) easyReversalCallbackHandler,
                        20, 0, GetOperationType.SHOW,
                        null));

        //////////// вызовы возвратов //////////////
        initButton(R.id.makeCardRefund, v -> {
            clientInterface.cancel();
            clientInterface.getTransactionManager()
                    .getTransactionsList(getTransactionListForRefundCallbackHandler, 20, 0,
                            GetOperationType.SHOW, null);
        });

        initButton(R.id.makeCashRefund, v -> {
            clientInterface.cancel();
            clientInterface.getTransactionManager()
                    .getTransactionsList((GetTransactionsListCallbackHandler) easyCashRefundCallbackHandler, 20,
                            0, GetOperationType.SHOW, null);
        });

        initButton(R.id.makeAlipayRefund, v -> clientInterface.getTransactionManager()
                .getTransactionsList(
                        (GetTransactionsListCallbackHandler) easyAlipayRefundCallbackHandler,
                        20, 0, GetOperationType.SHOW,
                        null));

        //////////// получение списка мерчантов //////////////
        initButton(R.id.getMerchantUsers, v -> clientInterface.getAuthorizationManager()
                .getMerchantUsers(getMerchantUsersCallbackHandler, 1000,
                        0));

        //////////// повторная отправка чека на почту //////////////
        initButton(R.id.resendReceipt, v -> clientInterface.getTransactionManager()
                .getTransactionsList(
                        (GetTransactionsListCallbackHandler) resendReceiptCallbackHandler,
                        20, 0, GetOperationType.SHOW,
                        null));

        //////////// получение детальной информации о транзакции //////////////
        initButton(R.id.getTransactionDetails, v -> clientInterface.getTransactionManager()
                .getTransactionsList(
                        (GetTransactionsListCallbackHandler) getTransactionDetailsCallbackHandler,
                        20, 0,
                        GetOperationType.SHOW,
                        null));

        //////////// получение детальной информации о текущей транзакции//////////////
        initButton(R.id.getCurrentTransactionDetails,
                v -> clientInterface.getTransactionManager().getTransactionDetails(false));

        //////////// получение спика транзакций с использованием фильтра //////////////
        initButton(R.id.getTransactionListFilter, v -> clientInterface.getTransactionManager()
                .getTransactionsList(
                        (GetTransactionsListCallbackHandler) getTransactionDetailsCallbackHandler,
                        20, 0, GetOperationType.SEARCH,
                        new TransactionFilterData.Builder().setScanerCode(
                                "6354635635736647656").build()));

        //////////// отправка данных для регистрации mpos - дополнительный функционал при активации//////////////
        findViewById(R.id.sendRegisterRequest).setOnClickListener(v -> {
            String url = "https://test.ponkratenko.ru";
            clientInterface.getConfigurationManager()
                    .sendRegisterRequest(sendRegisterRequestCallbackHandler, getRegisterRequestData(), url);
        });

        //запись на терминал ключей tmk, tpk
        findViewById(R.id.writeTerminalKeys).setOnClickListener(v -> {
            String url = "https://test.ponkratenko.ru";
            Set keysForDynamicUpdate = new HashSet<TerminalKeyType>() {{
                add(TerminalKeyType.Tak);
                add(TerminalKeyType.Tpk);
            }};
            clientInterface.getCardReaderManager()
                    .loadTerminalKeys(new LoadTerminalKeysCallbackHandlerImpl(this), keysForDynamicUpdate);
        });

        //////////// закрытие смены и сверка с сервером //////////////
        initButton(R.id.closeDay,
                v -> clientInterface.getTransactionManager().closeDay(closeDayCallbackHandler));

        //////////// добавление принтера в систему с возможностью печати во время транзакций //////////////
        initButton(R.id.addPrinter, v -> clientInterface.getPrinterManager()
                .addNewPrinter(printingCallbackHandler,
                        PrinterSeries.NEW_PRINTER));

        //////////// удаление принтера из системы //////////////
        initButton(R.id.deletePrinter,
                v -> clientInterface.getPrinterManager().clearSavedPrinterName());

        initButton(R.id.printFiscal, v -> {
            clientInterface.cancel();
            clientInterface.getPrinterManager()
                    .printFiscalTransactionCheck(printingCallbackHandler, DataCreatorUtils.makeFiscalData());
        });

        initButton(R.id.printSlipCheck, v -> {
            clientInterface.cancel();
            clientInterface.getPrinterManager()
                    .printFirstSlipTransactionCheck(printingCallbackHandler, DataCreatorUtils.makeSlipData(true),
                            SlipType.ERROR);
        });

        initButton(R.id.printReportX, v1 -> {
            clientInterface.cancel();
            clientInterface.getPrinterManager().printReport(printingCallbackHandler, PrintingType.X_REPORT);
        });
        initButton(R.id.printReportZ, v2 -> {
            clientInterface.cancel();
            clientInterface.getPrinterManager().printReport(printingCallbackHandler, PrintingType.Z_REPORT);
        });
        initButton(R.id.printFullReport, v1 -> {
            clientInterface.cancel();
            xReportCallbackHandler =
                    new XReportCallbackHandlerImpl(clientInterface, PrintingType.RECONCILIATION_FULL_REPORT, this);
            clientInterface.getPrinterManager().xReport(xReportCallbackHandler);
        });
        initButton(R.id.printShortReport, v2 -> {
            clientInterface.cancel();
            xReportCallbackHandler =
                    new XReportCallbackHandlerImpl(clientInterface, PrintingType.RECONCILIATION_SHORT_REPORT, this);
            clientInterface.getPrinterManager().xReport(xReportCallbackHandler);
        });

        initButton(R.id.printTemplate, v -> {
            clientInterface.cancel();
            clientInterface.getPrinterManager().printTemplate(printingCallbackHandler,
                    new ExternalTemplateData.Builder().printingTemplate(buildPrintingTemplate()).build());
        });

        initButton(R.id.readBarCode, v2 -> showDialogScanner());

        findViewById(R.id.versionStore).setOnClickListener(v -> {
            String result = clientInterface.getExternalApiManager().getExternalStoreVersion();
            Toast.makeText(this, result + "", Toast.LENGTH_SHORT).show();
        });

        findViewById(R.id.versionTracker).setOnClickListener(v -> {
            String result = clientInterface.getExternalApiManager().getExternalTrackerVersion();
            Toast.makeText(this, result + "", Toast.LENGTH_SHORT).show();
        });

        String savedServerUrl = PreferencesManager.loadStringField(this, PreferencesManager.Field.SERVER_URL,
                getString(R.string.default_server_address_mpos_5_0_test));
        String serverUrl;
        if (savedServerUrl != null) {
            serverUrl = savedServerUrl;
        } else {
            serverUrl = getString(R.string.default_server_address_mpos_5_0_test);
        }
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("Choose server");

        EditText serverAddressForm = new EditText(this);
        serverAddressForm.setText(serverUrl);

        builder.setView(serverAddressForm);
        builder.setPositiveButton("OK", (dialog, which) -> {
            String model1 = Build.MODEL;
            String brand2 = Build.BRAND;
            String serverAddress = serverAddressForm.getText().toString();
            PreferencesManager.saveStringField(M4BankActivity.this, PreferencesManager.Field.SERVER_URL, serverAddress);

            clientInterface = M4BankMposClient.getInstance(
                    new M4BankMposParameters(
                            Format.JSON,
                            "rus",
                            null,
                            this,
                            new SessionExpiringCallbackHandlerImpl(),
                            "appName",
                            ServerChoose.API_5_0,
                            new ConfigurationSettings
                                    .Builder()
                                    .printerUsed(true)
                                    .umkaEnabled(true)
                                    .networkConfiguration(createNetworkConfiguration(serverAddress))
                                    .terminalConfiguration(createTerminalConfiguration())
                                    .build())
            );
            dialog.dismiss();
        });

        builder.create().show();

        //Создание словаря
        DictionaryCore aisinoDictionary =
                new DictionaryCore(new HashMap<LanguageCore, HashMap<MessageCore, String>>() {{
                    put(LanguageCore.English, new HashMap<MessageCore, String>() {{
                        put(MessageCore.AisinoA90OfflinePin, "Please enter offline PIN");
                        put(MessageCore.AisinoA90OfflinePinRemain1, "Please enter offline PIN (Last try)");
                        put(MessageCore.AisinoA90OfflinePinRemain2, "Please enter offline PIN (Remain: 2)");
                        put(MessageCore.AisinoA90OfflinePinRemain3, "Please enter offline PIN (Remain: 3)");
                        put(MessageCore.AisinoA90OfflinePinRemain4, "Please enter offline PIN (Remain: 4)");
                        put(MessageCore.AisinoA90OnlinePin, "Please enter online PIN");
                        put(MessageCore.AisinoA90CompletingTransaction, "");
                        put(MessageCore.AisinoA90ContactlessMessage, "Please tap card");
                        put(MessageCore.AisinoA90ContactMessage, "Please insert card");
                        put(MessageCore.AisinoA90ReadSuccess, "PROCESSING");
                        put(MessageCore.AisinoA90InputPWD, "enter pin");
                        put(MessageCore.AisinoA90DefaultBottomButtonsText, "Cancel Clear Done");
                        put(MessageCore.AisinoPinpadCompleted, "COMPLETED");
                        put(MessageCore.AisinoPinpadDeclined, "DECLINED");
                        put(MessageCore.AisinoPinpadAmountHint, "");
                        put(MessageCore.KztCurrency, "KZT");
                        put(MessageCore.BynCurrency, "BYN");
                        put(MessageCore.EurCurrency, "EUR");
                        put(MessageCore.GelCurrency, "GEL");
                        put(MessageCore.JpyCurrency, "JPY");
                        put(MessageCore.KwdCurrency, "KWD");
                        put(MessageCore.RubCurrency, "RUB");
                        put(MessageCore.UsdCurrency, "USD");
                        put(MessageCore.AisinoPinpadScanning, "Text for test");
                        put(MessageCore.AisinoPinpadScanningCompleted, "Success for test");
                    }});
                    put(LanguageCore.Russian, new HashMap<MessageCore, String>() {{
                        put(MessageCore.AisinoA90OfflinePin, "Введите ПИН");
                        put(MessageCore.AisinoA90OfflinePinRemain1, "ПИН (Последняя попытка)");
                        put(MessageCore.AisinoA90OfflinePinRemain2, "ПИН (Осталось попыток: 2)");
                        put(MessageCore.AisinoA90OfflinePinRemain3, "ПИН (Осталось попыток: 3)");
                        put(MessageCore.AisinoA90OfflinePinRemain4, "ПИН (Осталось попыток: 4)");
                        put(MessageCore.AisinoA90OnlinePin, "Введите ПИН");
                        put(MessageCore.AisinoA90CompletingTransaction, "");
                        put(MessageCore.AisinoA90ContactlessMessage, "Предъявите карту");
                        put(MessageCore.AisinoA90ContactMessage, "Предъявите карту");
                        put(MessageCore.AisinoA90ReadSuccess, "ОБРАБОТКА");
                        put(MessageCore.AisinoA90InputPWD, "введите пин");
                        put(MessageCore.AisinoA90DefaultBottomButtonsText, "Отмена Очистить Готово");
                        put(MessageCore.AisinoPinpadCompleted, "ОДОБРЕНО");
                        put(MessageCore.AisinoPinpadDeclined, "ОТКЛОНЕНО");
                        put(MessageCore.AisinoPinpadAmountHint, "");
                        put(MessageCore.KztCurrency, "KZT");
                        put(MessageCore.BynCurrency, "BYN");
                        put(MessageCore.EurCurrency, "EUR");
                        put(MessageCore.GelCurrency, "GEL");
                        put(MessageCore.JpyCurrency, "JPY");
                        put(MessageCore.KwdCurrency, "KWD");
                        put(MessageCore.RubCurrency, "RUB");
                        put(MessageCore.UsdCurrency, "USD");
                        put(MessageCore.AisinoPinpadScanning, "Скан...");
                        put(MessageCore.AisinoPinpadScanningCompleted, "Успешно");
                    }});
                }});

        //обновление словаря в библиотеке ридера
        initButton(R.id.updateDictionary, v -> updateDictionary(aisinoDictionary));

        // отмена неуспешной операции, которая сохранена в холдере
        initButton(R.id.makeReversalSavedUnsuccessfulOperation, v ->
                clientInterface.getTransactionManager()
                        .makeReversalSavedUnsuccessfulOperation(easyReversalSavedOperationCallbackHandler));
    }

    private void initButton(int id, View.OnClickListener onClickListener) {
        findViewById(id).setOnClickListener(onClickListener);
    }

    private void initLoginForm() {
        EditText loginField = findViewById(R.id.login);
        EditText passwordField = findViewById(R.id.password);
        loginField.setText(
                PreferencesManager.loadStringField(M4BankActivity.this, PreferencesManager.Field.LOGIN, login));
        passwordField.setText(
                PreferencesManager.loadStringField(M4BankActivity.this, PreferencesManager.Field.PASSWORD, password));
        initButton(R.id.authorize, v -> {
            login = loginField.getText().toString();
            password = passwordField.getText().toString();
            PreferencesManager.saveStringField(M4BankActivity.this, PreferencesManager.Field.LOGIN, login);
            PreferencesManager.saveStringField(M4BankActivity.this, PreferencesManager.Field.PASSWORD, password);
            clientInterface.getAuthorizationManager().authorize(authorizationCallbackHandler);
        });
    }

    private TerminalConfiguration createTerminalConfiguration() {
        return new TerminalConfiguration.Builder()
                .energySaverModeTime(150)
                .pinLengthsArray(new byte[]{4, 6})
                .shutDownModeTime(300)
                .deviceType(new DeviceTypeDefiner().define())
                .build();
    }

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

    private void showDialogScanner() {
        String[] listItems = {"custom", "default"};
        AlertDialog.Builder builder = new AlertDialog.Builder(M4BankActivity.this);
        builder.setTitle("Choose scanner:");
        builder.setItems(listItems, (dialog, which) -> showScanner(which));
        AlertDialog dialog = builder.create();
        dialog.show();
    }

    private void showScanner(int which) {
        boolean isCustom;
        if (which == 0) {
            isCustom = true;
        } else {
            isCustom = false;
        }
        clientInterface.getCardReaderManager().scanBarCode(scanBarCodeCallbackHandler,
                new ScanBarCodeScreenDataInput.Builder()
                        .setShowCustom(isCustom)
                        .setShowNextButton("true")
                        .setNextButtonText("Next button")
                        .setNextButtonTextColor("#999888")
                        .setNextButtonTextSize("20")
                        .setTitleBarText("Qr Scanner")
                        .setTitleTextSize("20")
                        .setTitleTextColor("#123456")
                        .setTitleColor("#987123")
                        .setDescriptionText("Описание")
                        .setDescriptionTextColor("#564637")
                        .setDescriptionTextSize("20")
                        .setScanHeight("200")
                        .setScanWidth("600")
                        .setSummText("2000")
                        .setSummColor("#666777")
                        .setSummSize("20")
                        .build());
    }

    private void updateDictionary(DictionaryCore dictionaryCore) {
        clientInterface.getConfigurationManager().updateDictionary(dictionaryCore);
    }

    private void getReaderInformation() {
        clientInterface.getCardReaderManager().getCardReaderInformation(getCardReaderInformationCallbackHandler);
    }

    @Override
    protected void onStart() {
        super.onStart();
        //
        //        ((EditText) findViewById(R.id.code)).setText("roam");
        ////        ((EditText) findViewById(R.id.code)).setText("201");
        //        ((EditText) findViewById(R.id.pin)).setText("1111");
        ////        ((EditText) findViewById(R.id.login)).setText("61");
        ////        ((EditText) findViewById(R.id.login)).setText("test2");
        ////        ((EditText) findViewById(R.id.login)).setText("dm@centercorptech.net");
        //        ((EditText) findViewById(R.id.login)).setText("ap@m4bank.com");
        ////        ((EditText) findViewById(R.id.password)).setText("qwer");
        //        ((EditText) findViewById(R.id.password)).setText("1111");
        ////        ((EditText) findViewById(R.id.password)).setText("1111");
    }

    @Override
    protected void onDestroy() {
        Timber.d("Shutdown");
        if (clientInterface != null) {
            clientInterface.shutdown();
        }
        super.onDestroy();
    }

    private RegisterRequestData getRegisterRequestData() {
        String code = "1" + (int) (Math.random() * 1000) + "" + (int) (Math.random() * 1000) + "" +
                (int) (Math.random() * 1000);
        String date = new SimpleDateFormat("yyyy-MM-dd H:m:s").format(new Date());
        String acquiringType = "mPOS";
        String ip = "169.254.10.10";
        try {
            WifiManager wm = (WifiManager) getApplicationContext().getSystemService(WIFI_SERVICE);
            ip = Formatter.formatIpAddress(wm.getConnectionInfo().getIpAddress());
        } catch (Exception e) {
            e.printStackTrace();
        }
        RegisterRequestData result = new RegisterRequestData(code, date, acquiringType, ip);

        result.setWebSite("http://fgfdgsfgsd.ru");
        result.setRegion("г. Москва");
        result.setCity("Moscow");
        result.setOrganizationName("AlexCorp");
        result.setInn("5785678");
        result.setIndustry("dghdfgh");
        result.setCellPointsCount("44");
        result.setContactName("Alex");
        result.setEmail("Alex@alex.com");
        result.setPhone("+79859999999");
        result.setUsingCard(true);
        result.setAgreement(true);

        return result;
    }

    public long getAmount() {
        long amount;
        try {
            amount = Long.parseLong(((EditText) findViewById(R.id.amountField)).getText().toString());
        } catch (Exception any) {
            amount = 1;
        }
        return amount;
    }

    public HashMap<String, Object> getStyle(String style) {

        HashMap<String, Object> style1 = new HashMap<>();
        style1.put("TitleBackGroundColor", "#DB3F34");
        style1.put("VirtualPinPadStyle", 6);
        style1.put("PatternForAmountAndCurrency", "%s $");
        style1.put("setBottomBtnText", new String[]{"Cancel", "Clear", "Done"});

        HashMap<String, Object> style2 = new HashMap<>();
        style2.put("TitleBackGroundColor", "#909090");
        style2.put("VirtualPinPadStyle", 7);
        style2.put("PatternForAmountAndCurrency", "$ %s");
        style2.put("setBottomBtnText", new String[]{"Отмена", "Очистить", "Готово"});
        style2.put("amountTextSize", 32);
        style2.put("amountTextColor", "#333111");
        style2.put("amountTextFont", "sans_serif_bold_italic");
        style2.put("messageTextSize", 18);
        style2.put("messageTextColor", "#333aaa");
        style2.put("messageTextFont", "sans_serif_bold_italic");
        style2.put("keyboardNumbersTextColor", "#111ccc");
        style2.put("keyboardNumbersTextSize", 24);
        style2.put("keyboardNumbersTextFont", "sans_serif_bold_italic");
        style2.put("bottomButtonsTextSize", 14);
        style2.put("bottomButtonsTextColor", "#ccc666");
        style2.put("bottomButtonsTextFont", "sans_serif_bold_italic");

        switch (style) {
            case "Style 1":
                return style1;
            case "Style 2":
                return style2;
            default:
                return style1;
        }
    }

    public void showSelectStyleDialog(CardPaymentCallbackHandlerImpl.SelectStyleListener selectStyleListener) {
        ArrayList<String> styles = new ArrayList<>();
        styles.add("Style 1");
        styles.add("Style 2");
        runOnUiThread(() ->
                new SelectElementDialog<>(M4BankActivity.this, styles, new SelectDialogCallback<String>() {
                    @Override
                    public void onElementSelected(String element) {
                        VirtualPinKeyboardData virtualPinKeyboardData =
                                new VirtualPinKeyboardData.Builder(getStyle(element)).build();
                        selectStyleListener.onSelectStyle(virtualPinKeyboardData);
                    }

                    @Override
                    public void onCancelSelection() {

                    }
                }).show()
        );
    }

    private PrintingTemplate buildPrintingTemplate() {
        return new PrintingTemplate.Builder()
                .append(new BarcodeCheckObject(Align.Center, 100, 300, true, "Hello kitty"))
                .append(new StringCheckObject(new StringSpan.Builder("Test short simple string").build()))
                .append(new StringCheckObject(new StringSpan.Builder(
                        "Test long simple string. It's a pretty long string for being more that check with.").build()))
                .append(new StringCheckObject(new StringSpan.Builder("Test short italic center string.")
                        .alignment(Align.Center)
                        .textStyle(TextStyle.Italic)
                        .build()))
                .append(new StringCheckObject(new StringSpan.Builder("Test bold italic right large font string.")
                        .alignment(Align.Right)
                        .fontSize(30)
                        .textStyle(TextStyle.ItalicBold)
                        .build()))
                .append(new StringCheckObject(new StringSpan.Builder("Test gray left small string.")
                        .graylevel(5)
                        .fontSize(15)
                        .build()))
                .append(new QRCodeCheckObject(Align.Center, 100, "Hello kitty"))
                .append(new ImageCheckObject(
                        BitmapFactory.decodeResource(getResources(), android.R.drawable.ic_menu_call)))
                .build();
    }
}
