// import { Logger } from "./logger.js";
// import { UpdateDisplayListener } from "./updateDisplay.js";
// import { dumpValue, loading } from "./utils.js";
// import { PrimaryListener } from "./primaryListener.js";
// import { Transactions } from "./transaction.js";

class ECR {
    // create advanced ecr
    constructor() {
        this.ip = "";

        this.port = "80";

        this.userId = -1;

        this.posId = "";

        this.integratedKey = "";

        this.name = "";

        this.manufacturerName = "";

        this.version = "";

        this.integratedReceipt = true;

        this.integratedSurcharge = true;

        this.lastMerchantReceipt = "";

        this.language = "en-AU";

        // timapi is ready to be used
        this.isReady = false;

        this.connected = false;

        this.loggedin = false;

        this.activated = false;

        this.initialConnection = false;

        this.disposeConnection = false;

        // request in progress
        this.requestInProgress = undefined;

        // logger
        this.logger = new Logger();

        // terminal if present
        this.terminal = undefined;

        // transactions helper
        this.transactions = new Transactions();

        this.listener = new Listener();

        // ready callback
        this.timapiFinishedLoading();
    }

    // Log message
    log(message) {
        if (this.isReady) {
            timapi.log(message);
        } else {
            this.logger.info(message);
        }
    }

    // download logs and receipts
    downloadLogs() { }

    // Ensure terminal is created if absent. Returns the terminal instance.
    ensureTerminal() {
        if (this.terminal) {
            return this.terminal;
        }

        // create terminal settings
        var settings = new timapi.TerminalSettings();
        settings.connectionIPString = this.ip;
        settings.connectionIPPort = this.port;
        settings.integratorId = this.integratedKey;
        settings.guides = this.guidesSetFromSelectedGuideParams();
        settings.fetchBrands = false;
        settings.autoCommit = false;
        settings.enableKeepAlive = true;
        settings.dcc = false;
        settings.partialApproval = false;
        settings.tipAllowed = true;
        settings.fastNtfMode = true;

        // create terminal
        this.terminal = new timapi.Terminal(settings);

        // set pos and user id
        this.terminal.setUserId(this.userId);
        this.terminal.setPosId(this.posId);

        // ecr info
        let ei = new timapi.EcrInfo();
        ei.type = timapi.constants.EcrInfoType.ecrApplication;
        ei.name = this.name;
        ei.manufacturerName = this.manufacturerName;
        ei.version = this.version;
        this.terminal.addEcrData(ei);
        this.log(dumpValue(this.terminal.getEcrData()));

        // print options
        // let printFormat = this.integratedReceipt
        //     ? timapi.constants.PrintFormat.normal
        //     : timapi.constants.PrintFormat.onDevice;

        // let printOptions = new Set();
        // if (document.getElementById("paramValuePrintSupressHeader").checked) {
        //   printOptions.add(timapi.constants.PrintFlag.suppressHeader);
        // }
        // if (document.getElementById("paramValuePrintSupressSignature").checked) {
        //   printOptions.add(timapi.constants.PrintFlag.suppressSignature);
        // }
        // if (document.getElementById("paramValuePrintSupressEcrInfo").checked) {
        //   printOptions.add(timapi.constants.PrintFlag.suppressEcrInfo);
        // }
        // if (document.getElementById("paramValuePrintSupressEftInfo").checked) {
        //   printOptions.add(timapi.constants.PrintFlag.suppressEftInfo);
        // }

        // this.terminal.setPrintOptions([
        //     new timapi.PrintOption(
        //         timapi.constants.Recipient.cardholder,
        //         printFormat,
        //         40,
        //         printOptions
        //     ),
        //     new timapi.PrintOption(
        //         timapi.constants.Recipient.merchant,
        //         printFormat,
        //         40,
        //         printOptions
        //     ),
        // ]);
        // this.log(dumpValue(this.terminal.getPrintOptions()));

        // receipt formatter
        // switch (document.getElementById("paramValuePrintReceiptFormatter").value) {
        //   case "compact":
        //     this.terminal.setCompactReceiptFormatter();
        //     break;

        //   case "superCompact":
        //     this.terminal.setSuperCompactReceiptFormatter();
        //     break;

        //   case "ultraCompact":
        //     this.terminal.setUltraCompactReceiptFormatter();
        //     break;

        //   case "normal":
        //   default:
        //     this.terminal.setNormalReceiptFormatter();
        //     break;
        // }
        // this.terminal.setNormalReceiptFormatter();

        // add listener
        this.terminal.addListener(this.listener);

        return this.terminal;
    }

    // Dispose of terminal if present
    disposeTerminal() {
        if (!this.terminal) {
            return;
        }

        this.log("ecr.disposeTerminal()");
        this.requestInProgress = undefined;
        this.terminal.dispose();
        this.terminal = undefined;
    }

    // TimApi finished loading and is ready to be used
    async timapiFinishedLoading() {
        loading.show();
        this.log("ecr.timapiFinishedLoading()");
        await this.loadConfiguration();
        this.logger.activate();
        this.logger.saveLogs();
        loading.hide();
    }

    // Page unloading. Clean up everything requiring explicit cleaning up.
    // Now with terminals this dispose is not mandatory since closing a page also
    // shuts down the JavaScript VM instance which in turns frees all memory.
    // we do it here to be on the safe side
    pageIsUnloading() {
        this.log("ecr.pageIsUnloading()");
        this.disposeTerminal();
    }

    // guides set from selected guide parameters
    guidesSetFromSelectedGuideParams() {
        return [
            timapi.constants.Guides.retail,
            timapi.constants.Guides.gastro,
        ];
    }

    // load configuration
    async loadConfiguration() {
        console.debug("ecr.loadConfiguration machineID:", machineID);
        $("#MachineID").val(machineID);
        try {
            const result = await $.ajax({
                type: "GET",
                headers: {
                    Accept: "application/json; charset=utf-8",
                    ContentType: "application/json; charset=utf-8",
                    MerchantId: merchantId,
                    BranchId: branchId,
                },
                dataType: "json",
                contentType: "application/json;charset=UTF-8",
                url: "/api/eft/eftMachine?machineID=" + machineID + "&Seq=" + Seq,
            });
            console.debug("ecr.loadConfiguration response.result:", result);
            if (result.Code == 1000) {
                const { Data } = result;
                $("#EFTAddress").val(Data.EftPosAddress);
                $("#EFTPort").val(Data.EftPort);
                this.ip = Data.EftPosAddress;
                this.port = Data.EftPort;
                this.integratedKey = Data.IntegrationKey;
                this.name = Data.PosProductName;
                this.manufacturerName = Data.PosProductVendor;
                this.version = Data.PosProductVersion;
                this.userId = 1;
                this.posId = machineID;
                if (Data.EftPosAddress !== "" && Data.EftPort !== 0) {
                    this.isReady = true;
                    $("#EFTAddress").prop("disabled", true);
                    $("#EFTPort").prop("disabled", true);
                    $("#btn-save").hide();
                    $("#btn-modify").show();
                    $("#btn-test").show();
                    this.actionInitConnection();
                }
            }
        } catch (error) {
            console.debug("ecr.loadConfiguration response.error:", error);
        }
    }

    async actionSaveSettings() {
        if (validate()) {
            loading.show();
            $("#btn-save").prop("disabled", true);
            ecr.actionDispose();
            const request = {};
            request.MachineID = $("#MachineID").val();
            request.EftPosAddress = $("#EFTAddress").val();
            request.EftPort = $("#EFTPort").val();
            request.EftEnvironment = 2;
            request.IntegratedReceipt = true;
            request.IntegratedSurcharge = true;
            request.EFTPOSType = EFTPOSType;
            request.Seq = Seq;
            console.debug("ecr.saveSettings request.params:", request);
            try {
                await $.ajax({
                    type: "POST",
                    headers: {
                        Accept: "application/json; charset=utf-8",
                        ContentType: "application/json; charset=utf-8",
                        MerchantId: merchantId,
                        BranchId: branchId,
                    },
                    url: "/api/eft/pairCallback",
                    data: JSON.stringify(request),
                    dataType: "json",
                    contentType: "application/json;charset=UTF-8",
                });
                this.ip = $("#EFTAddress").val();
                this.port = $("#EFTPort").val();
                this.isReady = true;
                $("#btn-save").prop("disabled", false).hide();
                $("#EFTAddress").prop("disabled", true);
                $("#EFTPort").prop("disabled", true);
                $("#btn-modify").show();
                $("#btn-test").show();
                ecr.actionInitConnection();
            } catch (error) {
                console.debug("ecr.saveSettings error:", error);
                updateDisplayContent("Save Failure");
                $("#btn-save").prop("disabled", false);
            }
            loading.hide();
        }
    }

    actionInitConnection() {
        if (!this.connected) {
            this.initialConnection = true;
            this.actionConnect();
            return;
        }

        if (!this.loggedin) {
            this.initialConnection = true;
            this.actionLogin();
            return;
        }

        if (!this.activated) {
            this.initialConnection = false;
            this.actionActivate();
            return;
        }

        this.initialConnection = false;
    }

    actionDisposeConnection() {
        if (this.activated) {
            this.disposeConnection = true;
            this.actionDeactivate();
            return;
        }

        if (this.loggedin) {
            this.disposeConnection = true;
            this.actionLogout()
            return;
        }

        if (this.connected) {
            this.disposeConnection = false;
            this.actionDisconnect();
            return;
        }

        this.disposeConnection = false;
    }

    // actions
    actionConnect() {
        if (!this.isReady) {
            return;
        }

        this.requestInProgress = timapi.constants.RequestType.connect;
        return this.ensureTerminal().connectAsync();
    }

    actionDisconnect() {
        if (!this.isReady) {
            return;
        }
        this.ensureTerminal().disconnectAsync();
    }

    actionLogin() {
        if (!this.isReady) {
            return;
        }

        this.ensureTerminal().loginAsync();

        this.requestInProgress = timapi.constants.RequestType.login;
    }

    actionLogout() {
        if (!this.isReady) {
            return;
        }

        this.ensureTerminal().logoutAsync();

        this.requestInProgress = timapi.constants.RequestType.logout;
    }

    actionActivate() {
        if (!this.isReady) {
            return;
        }

        this.ensureTerminal().activateAsync();

        this.requestInProgress = timapi.constants.RequestType.activate;
    }

    actionDeactivate() {
        if (!this.isReady) {
            return;
        }
        this.ensureTerminal().deactivateAsync();

        this.requestInProgress = timapi.constants.RequestType.deactivate;
    }

    actionDispose() {
        if (!this.isReady) {
            return;
        }
        this.disposeTerminal();
    }

    actionApplicationInfo() {
        if (!this.isReady) {
            return;
        }
        this.ensureTerminal().applicationInformationAsync();

        this.requestInProgress =
            timapi.constants.RequestType.applicationInformation;
    }

    actionDccRates() {
        if (!this.isReady) {
            return;
        }
        this.ensureTerminal().dccRatesAsync();

        this.requestInProgress = timapi.constants.RequestType.dccRates;
    }

    actionHardwareInfo() {
        if (!this.isReady) {
            return;
        }
        this.ensureTerminal().hardwareInformationAsync();

        this.requestInProgress = timapi.constants.RequestType.hardwareInformation;
    }

    actionSystemInfo() {
        if (!this.isReady) {
            return;
        }
        this.ensureTerminal().systemInformationAsync();

        this.requestInProgress = timapi.constants.RequestType.systemInformation;
    }

    actionSoftwareUpdate() {
        if (!this.isReady) {
            return;
        }
        this.ensureTerminal().softwareUpdateAsync();

        this.requestInProgress = timapi.constants.RequestType.softwareUpdate;
    }

    actionReconciliation() {
        if (!this.isReady) {
            return;
        }
        this.ensureTerminal().reconciliationAsync();

        this.requestInProgress = timapi.constants.RequestType.reconciliation;
    }

    actionReboot() {
        if (!this.isReady) {
            return;
        }
        this.ensureTerminal().rebootAsync();

        this.requestInProgress = timapi.constants.RequestType.reboot;
    }

    actionReconfig() {
        if (!this.isReady) {
            return;
        }
        this.ensureTerminal().reconfigAsync();

        this.requestInProgress = timapi.constants.RequestType.reconfig;
    }

    actionTransaction(type, amount, tips, otherAmount, ref) {
        if (!this.isReady) {
            return;
        }
        const result = this.transactions.transaction(
            this.ensureTerminal(),
            type,
            amount,
            tips,
            otherAmount,
            ref
        )
        console.info('start transaction result: ', result)
        if (
            !result
        ) {
            return;
        }

        this.requestInProgress = timapi.constants.RequestType.transaction;
    }

    actionTransactionInfoRequest() {
        if (!this.isReady) {
            return;
        }
        this.ensureTerminal().transactionInfoRequestAsync();
        this.requestInProgress = timapi.constants.RequestType.transactionInfoRequest;
    } 

    actionCancel() {
        if (!this.isReady) {
            return;
        }

        let terminal = this.ensureTerminal();
        terminal.cancel();
    }

    actionRollback() {
        if (!this.isReady) {
            return;
        }

        this.ensureTerminal().rollbackAsync();

        this.requestInProgress = timapi.constants.RequestType.rollback;
    }

    actionCommit() {
        if (!this.isReady) {
            return;
        }

        this.ensureTerminal().commitAsync();

        this.requestInProgress = timapi.constants.RequestType.commit;
    }

    actionBalance() {
        if (!this.isReady) {
            return;
        }

        this.ensureTerminal().balanceAsync();

        this.requestInProgress = timapi.constants.RequestType.balance;
    }

    actionHoldCommit() {
        if (!this.isReady) {
            return;
        }

        this.ensureTerminal().holdCommit();
    }

    actionPrintOnTerminal() {
        if (!this.isReady) {
            return;
        }

        let ticketData = document.getElementById(
            "paramValueDialogPrintOnTerminal"
        ).value;
        this.ensureTerminal().printOnTerminalAsync(ticketData);

        this.requestInProgress = timapi.constants.RequestType.printOnTerminal;
        this.listenerEnableUI.updateUI();
    }

    actionBalanceInquiry() {
        if (!this.isReady) {
            return;
        }

        let terminal = this.ensureTerminal();

        let trxData = terminal.getTransactionData();
        // Trx Original Date
        let textTrxOriginalDate = document.getElementById(
            "paramValueTrxOriginalDate"
        ).value;
        if (textTrxOriginalDate !== "") {
            let dateTrxOriginalDate = new Date(textTrxOriginalDate);
            trxData.trxOriginalDate = timapi.TimeDate.fromDate(dateTrxOriginalDate);
        }
        // Language
        let textLanguage = document.getElementById("paramValueLanguage").value;
        trxData.language = textLanguage.length > 0 ? textLanguage : undefined;
        // Store all the new data
        terminal.setTransactionData(trxData);

        terminal.balanceInquiryAsync();

        this.requestInProgress = timapi.constants.RequestType.balanceInquiry;
        this.listenerEnableUI.updateUI();
    }

    actionGetActSeqCounter() {
        if (!this.isReady) {
            return;
        }
        timapi.log(
            `ActSeqCounter: ${dumpValue(this.ensureTerminal().getActSeqCounter())}`
        );
    }

    actionGetBrands() {
        if (!this.isReady) {
            return;
        }
        timapi.log(`Brands: ${dumpValue(this.ensureTerminal().getBrands())}`);
    }

    actionGetConfigData() {
        if (!this.isReady) {
            return;
        }
        timapi.log(
            `ConfigData: ${dumpValue(this.ensureTerminal().getConfigData())}`
        );
    }

    actionGetEcrData() {
        if (!this.isReady) {
            return;
        }
        timapi.log(`EcrData: ${dumpValue(this.ensureTerminal().getEcrData())}`);
    }

    actionGetFeatures() {
        if (!this.isReady) {
            return;
        }
        timapi.log(`Features: ${dumpValue(this.ensureTerminal().getFeatures())}`);
    }

    actionGetMerchantOptions() {
        if (!this.isReady) {
            return;
        }
        timapi.log(
            `MerchantOptions: ${dumpValue(
                this.ensureTerminal().getMerchantOptions()
            )}`
        );
    }

    actionGetPosId() {
        if (!this.isReady) {
            return;
        }
        timapi.log(`PosId: ${dumpValue(this.ensureTerminal().getPosId())}`);
    }

    actionGetPrintOptions() {
        if (!this.isReady) {
            return;
        }
        timapi.log(
            `PrintOptions: ${dumpValue(this.ensureTerminal().getPrintOptions())}`
        );
    }

    actionGetSettings() {
        if (!this.isReady) {
            return;
        }
        timapi.log(`Settings: ${dumpValue(this.ensureTerminal().getSettings())}`);
    }

    actionGetTerminalId() {
        if (!this.isReady) {
            return;
        }
        timapi.log(
            `TerminalId: ${dumpValue(this.ensureTerminal().getTerminalId())}`
        );
    }

    actionGetTerminalStatus() {
        if (!this.isReady) {
            return;
        }
        timapi.log(
            `TerminalStatus: ${dumpValue(this.ensureTerminal().getTerminalStatus())}`
        );
    }

    actionGetTransactionData() {
        if (!this.isReady) {
            return;
        }
        timapi.log(
            `TransactionData: ${dumpValue(
                this.ensureTerminal().getTransactionData()
            )}`
        );
    }

    actionGetUserId() {
        if (!this.isReady) {
            return;
        }
        timapi.log(`UserId: ${dumpValue(this.ensureTerminal().getUserId())}`);
    }
}
