<template id="tx-data">
    <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='output.css') }}">

    <div class="tx-data bg-dark-800 rounded-xl p-4">
        <div class="flex justify-between mb-2">
            <h3 class="mb-0">{{ _("Transaction Details") }}</h3>
            <p class="m-0 cursor-pointer" onclick="hidePageOverlay()" class="cursor-pointer" data-cy="transaction-details-screen-close-btn">Close</p>
        </div>
        <div class="tx-data-info"></div>
        <div class="note"></div>
    </div>
</template>
  
<script type="text/javascript">
    class TxDataElement extends HTMLElement {
        constructor() {
            super();
            // Create a shadow root
            var shadow = this.attachShadow({mode: 'open'});
            var style = document.getElementById('tx-data').content;
            var clone = style.cloneNode(true);

            this.el = clone.querySelector(".tx-data");
            this.note = clone.querySelector(".note");
            this.info = clone.querySelector(".tx-data-info");
            this.txid = this.getAttribute('data-txid');
            this.wallet = this.getAttribute('data-tx-wallet');
            this.btcUnit = this.getAttribute('data-btc-unit');
            this.price = this.getAttribute('data-price');
            this.symbol = this.getAttribute('data-symbol');
            this.note.innerText = `{{ _("Loading transaction details...\n\nTransaction ID:") }}" ${this.txid}`;
            this.fetchTxData();
        
            // Attach the created element to the shadow dom
            shadow.appendChild(clone);
        }
        
        async fetchRawTx(txid) {
            let url = `{{ url_for('wallets_endpoint_api.decoderawtx', wallet_alias='WALLET_ALIAS') }}`.replace("WALLET_ALIAS", this.wallet);
            var formData = new FormData();
            formData.append('txid', txid);
            formData.append('csrf_token', '{{ csrf_token() }}');
            try {
                const response = await fetch(
                    url,
                    {
                        method: 'POST',
                        body: formData
                    }
                );
                if(response.status != 200){
                    showError(await response.text());
                    return null;
                }
                const jsonResponse = await response.json();
                return jsonResponse;
            } catch(e) {
                this.note.innerText = '{{ _("Failed to load transaction details...") }}';
                console.log("Caught error fetching decoded transaction: ", e);
                showError(`{{ _("Failed to fetch data. Please refresh the page and retry.") }}`);
            }
            return null;
        }

        async fetchTxData() {
            let jsonResponse = await this.fetchRawTx(this.txid);
            if (jsonResponse !== null && jsonResponse.success) {
                console.log(jsonResponse);
                let rawtx = jsonResponse.rawtx;
                let walletName = jsonResponse.wallet_name;
                let tx = jsonResponse.tx;
                let walletLink = `{{ url_for('wallets_endpoint.wallet', wallet_alias='WALLET_ALIAS') }}`.replace("WALLET_ALIAS", this.wallet);
                let rawtxHTML = "";
                if(tx.is_purged) {
                    rawtxHTML += `
                    <div class="warning">
                        <p><b>{{ _( "This transaction (aka \"tx\") could not be found in your node's mempool!") }}</b></p>
                        <p data-style="text-align:left;">{{ _( "If the bitcoin network is very busy, nodes will start purging the pending txs with the lowest fees. Txs older than two weeks are also purged.") }}</p>
                        <p data-style="text-align:left;">{{ _( "A purged tx will never complete. Abandoning this tx will clear it from your wallet, making those funds spendable once again.") }}</p>
                        <p data-style="text-align:left;">{{ _( "But first verify that other nodes have also purged your tx! Enter the tx id into a public block explorer (warning: slight privacy leak). If the tx cannot be found, it is safe to abandon this tx.") }}</p>

                        <br/><br/>
                        <form method="POST" action="${walletLink}history/">
                            <input type="hidden" class="csrf-token" name="csrf_token" value="{{ csrf_token() }}"/>
                            <input type="hidden" name="action" value="abandon_tx"/>
                            <input type="hidden" name="txid" value="${this.txid}"/>
                            <button type="submit" name="action" value="abandontx" class="btn danger centered" data-style="max-width: 160px;">{{ _("Abandon transaction") }}</button>
                        </form>
                    </div>
                    `;
                }
                rawtxHTML += `
                <table class="tx-data-table -mx-4 mt-8">
                <tbody>
                <tr><td><span class="optional">{{ _("Transaction ID") }}:</span></td><td data-style="word-break: break-all;"><explorer-link data-type="tx" data-value="${this.txid}"></explorer-link></td></tr>
                <tr><td>From wallet:</td><td><a href=${walletLink}>${walletName}<a></td></tr>
                <tr><td>Size:</td><td>${rawtx.vsize} vbytes <span class="note">(${rawtx.size} bytes)</span></td></tr>
                `;
                if (tx.fee) {
                    let fee = tx.fee;
                    if(typeof tx.fee == "object"){
                        if("bitcoin" in tx.fee){
                            fee = tx.fee.bitcoin;
                        }
                    }
                    rawtxHTML += `
                        <tr><td>{{ _("Fee") }}:</td><td>${parseInt(-1e8 * fee)} sats</td></tr>
                        <tr><td>{{ _("Fee rate") }}:</td><td>${parseFloat((-1e8 * fee / rawtx.vsize).toFixed(2)).toString()} sat/vbyte</td></tr>
                    `;
                }
                if (tx.confirmations && tx.confirmations > 0) {
                    rawtxHTML += `
                        <tr><td>{{ _("Mined at block") }}:</td><td>${tx.blockheight}</td></tr>
                        <tr><td>{{ _("Block hash") }}:</td><td data-style="word-break: break-all;">${tx.blockhash}</td></tr>
                        <tr><td>{{ _("Block time") }}:</td><td>${new Date(tx.blocktime * 1000)} <span data-style="font-size: 0.9em;color: #ccc;">(${tx.blocktime})</span></td></tr>
                    `;
                }
                rawtxHTML += `
                    <tr><td>{{ _("Inputs count") }}:</td><td>${rawtx.vin.length}</td></tr>
                    <tr><td>{{ _("Outputs count") }}:</td><td>${rawtx.vout.length}</td></tr>
                `;
                rawtxHTML += `
                </tbody>
                </table>
                `;
                rawtxHTML += `<h3>Inputs</h3>`;
                for (let i in rawtx.vin) {
                    let bgColor = '#131a24';
                    let addressAndValue = '';
                    let jsonResponse = await this.fetchRawTx(rawtx.vin[i].txid);
                    if (jsonResponse !== null && jsonResponse.success) {
                        let spentOutput = jsonResponse.rawtx.vout[rawtx.vin[i].vout];

                        let address = (spentOutput.addresses && spentOutput.addresses.length == 1) ? spentOutput.addresses[0] : 'Unknown';
                        if (address == 'Unknown') {
                            address = (spentOutput.scriptPubKey.addresses && spentOutput.scriptPubKey.addresses.length == 1) ? spentOutput.scriptPubKey.addresses[0] : 'Unknown';
                        }
                        if (address == 'Unknown') {
                            address = spentOutput.scriptPubKey.address ? spentOutput.scriptPubKey.address : 'Unknown';
                        }
                        if (address == 'Unknown') {
                            address = spentOutput.address ? spentOutput.address : 'Unknown';
                        }
                        let isMine = await this.fetchAddressIsMine(address);
                        if (isMine) {
                            bgColor = '#925d07';
                        }
                        let labelAttr = "";
                        if ("label" in spentOutput) {
                            labelAttr = `data-label="${spentOutput.label}"`;
                        }
                        let serviceIdAttr = "";
                        if ("service_id" in spentOutput) {
                            serviceIdAttr = `data-service-id="${spentOutput.service_id}"`;
                        }
                        // assetlabel only exists for Liquid, for BTC it is just null
                        var amountAndUnit = formatBtcAmount(spentOutput.value, spentOutput.assetlabel, this.btcUnit == 'sat');
                        var price = formatPrice(spentOutput.value, spentOutput.assetlabel, this.symbol, this.price); 

                        addressAndValue = `
                            {{ _("Address:") }} <span style="word-wrap: break-word;">${address}</span><br>
                            {{ _("Label:") }} 
                            <address-label  style="display: inline-block; vertical-align: middle;"
                                data-copy-hidden="true"
                                data-address="${address}"
                                data-wallet="${this.wallet}"
                                ${labelAttr}
                                ${serviceIdAttr}>
                            </address-label><br>
                            {{ _("Value:") }} ${amountAndUnit} ${price}
                            `;
                    }

                    if ('coinbase' in rawtx.vin[i]) {
                        rawtxHTML += `
                        <p class="tx_info" data-style="text-align: left; background-color: ${bgColor};">
                            <b>{{ _("Input #") }}${i}</b><br><br>
                            <b>{{ _("Coinbase transaction") }}</b>
                            <br>
                        </p>
                        `;
                        continue;
                    }
                    if (jsonResponse.nonWalletTxId) {
                        let nonWalletTxId = jsonResponse.nonWalletTxId ? `<span>Not known, this is a non-wallet txid.</span>` : null
                        rawtxHTML += `
                            <p class="tx_info" data-style="text-align: left; background-color: ${bgColor};">
                                <b>{{ _("Input #") }}${i}</b><br><br>
                                {{ _("Transaction id") }}: <explorer-link data-style="word-break: break-all;" data-type="tx" data-value="${rawtx.vin[i].txid}"></explorer-link><br>
                                {{ _("Output index: ") }}${rawtx.vin[i].vout}<br>
                                {{ _("Address & value:") }} ${nonWalletTxId}
                            </p>
                        `;
                    }
                    else {
                        rawtxHTML += `
                            <p class="tx_info" data-style="text-align: left; background-color: ${bgColor};">
                                <b>{{ _("Input #") }}${i}</b><br><br>
                                {{ _("Transaction id") }}: <explorer-link data-style="word-break: break-all;" data-type="tx" data-value="${rawtx.vin[i].txid}"></explorer-link><br>
                                {{ _("Output index: ") }}${rawtx.vin[i].vout}<br>
                                ${addressAndValue}
                            </p>
                        `;

                    }
                }

                rawtxHTML += `<h3>{{ _("Outputs") }}</h3>`;
                for (let i in rawtx.vout) {
                    let address = rawtx.vout[i].addresses && rawtx.vout[i].addresses.length == 1 ? rawtx.vout[i].addresses[0] : 'Unknown';
                    if (address == 'Unknown') {
                        address = rawtx.vout[i].scriptPubKey.addresses && rawtx.vout[i].scriptPubKey.addresses.length == 1 ? rawtx.vout[i].scriptPubKey.addresses[0] : 'Unknown';
                    
                    }
                    if (address == 'Unknown') {
                        address = rawtx.vout[i].scriptPubKey.address ? rawtx.vout[i].scriptPubKey.address : 'Unknown';
                    }
                    if (address == 'Unknown') {
                        address = rawtx.vout[i].address ? rawtx.vout[i].address : 'Unknown';
                    }

                    let bgColor = '#131a24';
                    if ("index" in rawtx.vout[i]) {
                        // Only addresses from this wallet will have an index; isMine = True
                        bgColor = '#154984';
                    }

                    let labelAttr = "";
                    if ("label" in rawtx.vout[i]) {
                        labelAttr = `data-label="${rawtx.vout[i].label}"`;
                    } else if (address != "Unknown") {
                        labelAttr = `data-label="${address}"`;
                    }
                    let serviceIdAttr = "";
                    if ("service_id" in rawtx.vout[i]) {
                        serviceIdAttr = `data-service-id="${rawtx.vout[i].service_id}"`;
                    }
                    // assetlabel only exists for Liquid, for BTC it is just null
                    var amountAndUnit = formatBtcAmount(rawtx.vout[i].value, rawtx.vout[i].assetlabel, this.btcUnit == 'sat');
                    var price = formatPrice(rawtx.vout[i].value, rawtx.vout[i].assetlabel, this.symbol, this.price); 

                    rawtxHTML += `
                    <p class="tx_info" data-style="text-align: left; background-color: ${bgColor};">
                        <b>{{ _("Output #${i}") }}</b><br><br>
                        {{ _("Address:") }} <span style="word-break: break-all;">${address}</span><br>
                        {{ _("Label:") }} 
                        <address-label style="display: inline-block; vertical-align: middle;"
                            data-copy-hidden="true"
                            data-address="${address}"
                            data-wallet="${this.wallet}"
                            ${labelAttr}
                            ${serviceIdAttr}>
                        </address-label><br>
                        {{ _("Value:") }} ${amountAndUnit} ${price}
                    </p>
                    `;
                }
                
                this.info.innerHTML = rawtxHTML;
                this.note.innerText = "";
                return;
            };
            this.note.innerText = '{{ _("Failed to load transaction details...") }}';
        }
        
        async fetchAddressIsMine(address) {
            let url = `{{ url_for('wallets_endpoint_api.is_address_mine', wallet_alias='WALLET_ALIAS', address='ADDRESS') }}`.replace("WALLET_ALIAS", this.wallet).replace("ADDRESS", address);
            try {
                const response = await send_request(url, 'GET', '{{ csrf_token() }}'); 
                return response['is_mine'];
            }  catch(e) {
                showError(`{{ _("Failed to check is_address_mine...") }}`);
                showError(e);
            }
            return false;
        }
    }
    customElements.define('tx-data', TxDataElement);
</script>
