// Helper class handling transaction actions
class Transactions {
    // run transaction. return true if transaction has been started
    transaction(terminal, type, amount, tips, otherAmount, ref) {
        let trxParams = new TransactionParameters();
        trxParams.setType(type);
        trxParams.setAmount(amount);
        trxParams.setTips(tips);
        trxParams.setOtherAmount(otherAmount);
        trxParams.setEcrSeqCounter(ref);

        this.appendCommon(trxParams);

        switch (trxParams.trxType) {
            case timapi.constants.TransactionType.purchase:
                if (this.purchase(terminal, trxParams) === false) {
                    return false;
                }
                break;

            case timapi.constants.TransactionType.credit:
                if (this.credit(terminal, trxParams) === false) {
                    return false;
                }
                break;

            case timapi.constants.TransactionType.reversal:
                this.reversal(terminal, trxParams);
                break;

            case timapi.constants.TransactionType.cashAdvance:
                this.cashAdvance(terminal, trxParams);
                break;

            case timapi.constants.TransactionType.purchaseWithCashback:
                this.purchaseWithCashback(terminal, trxParams);
                break;

            default:
                timapi.log(`Transaction Type ${trxParams.trxType} not supported yet`);
                return false;
        }

        terminal.setTransactionData(trxParams.trxData);
        timapi.log(
            `Transaction data = ${dumpValue(terminal.getTransactionData())}`
        );

        console.info(trxParams);

        let merchantOptions = terminal.getMerchantOptions();

        let guides = terminal.getSettings().guides;

        let trxRequest = undefined;
        if (merchantOptions) {
            trxRequest = new timapi.TransactionRequest();
            if (trxParams.useAmount) {
                trxRequest.amount = trxParams.amount;
                if (trxParams.amount == undefined) {
                    if (
                        !confirm(
                            "NO valid amount is defined, which is mandatory.\n\nPress 'OK' to send anyway, or 'Cancel' to stop the request."
                        )
                    ) {
                        return false;
                    }
                }
            }
            if (trxParams.useAmountTip) {
                trxRequest.amountTip = trxParams.amountTip;
            }
            if (trxParams.useAmountOther) {
                trxRequest.amountOther = trxParams.amountOther;
                if (trxParams.amountOther == undefined) {
                    // Field "AmountOther" is mandatory for AdvancedRetail/PurchaseWithCashback (but optional for Banking/Combined)
                    if (
                        guides.has(timapi.constants.Guides.advancedRetail) &&
                        trxParams.trxType ==
                        timapi.constants.TransactionType.purchaseWithCashback
                    ) {
                        if (
                            !confirm(
                                "NO valid other amount is defined, which is mandatory.\n\nPress 'OK' to send anyway, or 'Cancel' to stop the request."
                            )
                        ) {
                            return false;
                        }
                    }
                }
            }
            trxRequest.transactionData = trxParams.trxData;

            if (merchantOptions) {
                trxRequest.merchantOptions = merchantOptions;
            }
            //trxRequest.userId = terminal.getUserId();
        }

        if (trxRequest) {
            terminal.transactionWithRequestAsync(trxParams.trxType, trxRequest);
        } else if (guides.has(timapi.constants.Guides.advancedRetail)) {
            terminal.transactionCashbackAsync(
                trxParams.trxType,
                trxParams.useAmount ? trxParams.amount : undefined,
                trxParams.useAmountOther ? trxParams.amountOther : undefined
            );
        } else if (guides.has(timapi.constants.Guides.gastro)) {
            terminal.transactionTipAsync(
                trxParams.trxType,
                trxParams.useAmount ? trxParams.amount : undefined,
                trxParams.useAmountTip ? trxParams.amountTip : undefined
            );
        } else {
            terminal.transactionAsync(
                trxParams.trxType,
                trxParams.useAmount ? trxParams.amount : undefined
            );
        }
        return true;

    }

    appendCommon(trxParams) {
        let trxData = trxParams.trxData;
        trxData.transRef = trxParams.transRef;
        trxData.transSeq = trxParams.transSeq;
        trxData.acqId = trxParams.acqId;
        trxData.acqTransRef = trxParams.acqTransRef;
        trxData.trmTransRef = trxParams.trmTransRef;
        trxData.transactionReason = trxParams.transactionReason;
        trxData.ecrSeqCounter = trxParams.ecrSeqCounter;
        trxData.posEntryMode = trxParams.posEntryMode;
        trxData.sixTrxRefNum = trxParams.sixTrxRefNum;
        this.appendMPKE(trxParams);
    }

    appendMPKE(trxParams) {
        let trxData = trxParams.trxData;
        trxData.cardRef = trxParams.cardRef;
        if (trxData.cardRef) {
            trxData.appExpirationDate = trxParams.appExpirationDate;
            trxData.cvc2 = trxParams.cvc2;
        }
    }

    appendGastro(terminal, trxParams) {
        if (terminal.getSettings().guides.has(timapi.constants.Guides.gastro)) {
            trxParams.trxData.amountTip = trxParams.amountTip;
            trxParams.useAmountTip = true;
            trxParams.trxData.tipAllowed = trxParams.tipAllowed;
        }
    }

    purchase(terminal, trxParams) {
        let trxData = trxParams.trxData;
        trxParams.useAmount = true;
        trxData.language = trxParams.language;
        trxData.dccAllowed = trxParams.dccAllowed;
        trxData.installmentAllowed = trxParams.installmentAllowed;
        trxData.partialApprovalAllowed = trxParams.partialApprovalAllowed;
        trxData.phoneAuthCode = trxParams.phoneAuthCode;
        this.appendGastro(terminal, trxParams);
    }

    credit(terminal, trxParams) {
        let trxData = trxParams.trxData;
        trxParams.useAmount = true;
        trxData.language = trxParams.language;
        trxData.installmentAllowed = trxParams.installmentAllowed;
        trxData.trxOriginalDate = trxParams.trxOriginalDate;
    }

    reversal(terminal, trxParams) {
        let trxData = trxParams.trxData;
        trxData.installmentAllowed = trxParams.installmentAllowed;
        trxData.phoneAuthCode = trxParams.phoneAuthCode;
        this.appendBanking(terminal, trxParams);
    }

    purchaseWithCashback(terminal, trxParams) {
        let trxData = trxParams.trxData;
        trxParams.useAmount = true;
        trxParams.useAmountOther = true;
        trxData.dccAllowed = trxParams.dccAllowed;
        trxData.deferredAuthInd = trxParams.deferredAuthInd;
        trxData.installmentAllowed = trxParams.installmentAllowed;
        trxData.partialApprovalAllowed = trxParams.partialApprovalAllowed;
        this.appendGastro(terminal, trxParams);
    }
}

class TransactionParameters {
    constructor() {
        // currency
        this.currency = timapi.constants.Currency.AUD;

        // transaction type
        this.trxType = undefined;

        // amount
        this.amount = undefined;
        this.useAmount = false;

        // amount tip
        this.amountTip = undefined;
        this.useAmountTip = false;

        // amount other
        this.amountOther = undefined;
        this.useAmountOther = false;

        // tip allowed
        this.tipAllowed = true;

        // transaction data
        this.trxData = undefined;

        // basket
        /*
            final NamedBasket basket = (NamedBasket)modelBasket.getSelectedItem();
            Basket requestBasket = null;
            */
        this.basket = undefined;

        // transaction reference
        this.transRef = undefined;

        // transaction sequence number
        this.transSeq = undefined;

        // acquirer id
        this.acqId = undefined;

        // acquirer transaction reference
        this.acqTransRef = undefined;

        // card reference
        this.cardRef = undefined;

        // phone auth code
        this.phoneAuthCode = undefined;

        // trm trans reference
        this.trmTransRef = undefined;

        // six transaction reference number
        this.sixTrxRefNum = undefined;

        // trx original date
        this.trxOriginalDate = undefined;

        // Language
        this.language = "en-AU";

        // Installment allowed
        this.installmentAllowed = false;

        // Deferred Auth Ind
        this.deferredAuthInd = false;

        // DCC Allowed
        this.dccAllowed = true;

        // ECR Sequence Counter
        this.ecrSeqCounter = undefined;

        // Transaction reason
        this.transactionReason = undefined;

        // App Expiration date
        this.appExpirationDate = undefined;

        // CVC2
        this.cvc2 = undefined;

        // Partial Approval Allowed
        this.partialApprovalAllowed = false;

        // Multi Currency flag
        this.multiCurrencyFlag = false;

        // transaction data
        this.trxData = new timapi.TransactionData();
    }

    setType(type) {
        this.trxType = timapi.constants.TransactionType.values().find(function (
            each
        ) {
            return each.name == type;
        });
    }

    setAmount(amount) {
        this.amount = timapi.Amount.fromMajorUnits(amount, this.currency);
    }

    setTips(amount) {
        this.amountTip = timapi.Amount.fromMajorUnits(amount, this.currency);
    }

    setOtherAmount(amount) {
        this.amountOther = timapi.Amount.fromMajorUnits(amount, this.currency);
    }

    setAcqTransRef(trxRef) {
        this.acqTransRef = trxRef;
    }

    setEcrSeqCounter(trxRef) {
        this.ecrSeqCounter = trxRef;
    }
}
