<template id="address-label">
    <style>
        .address-label-form {
            display: inline;
        }
        .service-icon {
            margin-top: -5px;
            margin-right: 0.25em;
            height:24px;
            vertical-align: middle;
        }
        .label {
            word-break: break-all;
            background: none;
            color: #fff;
            font-size: 1em;
            max-width: 80%;
            outline: none;
        }
        .explorer-link {
            text-decoration: none;
        }
        .explorer-link:hover {
            color: #fff;
            text-decoration: underline;
            cursor: pointer
        }
        .edit {
            background: none;
            border: none;
            padding: 0;
            margin: 0;
            width: 18px;
            cursor: pointer;
        }
        .cancel, .update {
            background: var(--cmap-border);
            border: 1px solid transparent;
            border-radius: 4px;
            padding: 8px 15px 8px 10px;
            color: #fff;
            font-size: 0.75em;
            text-align: center;
            align-items: center;
            justify-content: center;
            cursor: pointer;
            min-height: 33px;
            margin-left: 5px;
        }
        @media (hover: none) {
            .explorer-link:hover {
                text-decoration: none;
            }
            .explorer-link:active {
                text-decoration: underline;
            }
        }

        .hidden {
            display: none;
        }

        .svg-white {
            filter: invert(100%) sepia(0%) saturate(1%) hue-rotate(304deg) brightness(102%) contrast(101%);
        }
    </style>
    <form class="address-label-form">
        <input type="hidden" class="csrf-token" name="csrf_token" value="{{ csrf_token() }}"/>
        <img class="service-icon"/>
        <a target="_blank" class="explorer-link"><span class="label" autocomplete="off" spellcheck="false">{{ _("Fetching address label...") }}</span></a>
        <button type="button" class="btn edit" title="Edit label"><img src="{{ url_for('static', filename='img/edit.svg') }}" style="width: 22px; margin-bottom:-5px;" class="svg-white"/></button>
        <button type="button" class="btn update hidden">{{ _("Update") }}</button>
        <button type="button" class="btn cancel hidden">{{ _("Cancel") }}</button>
    </form>
</template>

<script type="text/javascript">
    class AddressLabelElement extends HTMLElement {
        constructor() {
            super();
            // Create a shadow root
            var shadow = this.attachShadow({mode: 'open'});
            var style = document.getElementById('address-label').content;
            var clone = style.cloneNode(true);
            this.el = clone.querySelector(".address-label-form");
            this.serviceIconImg = clone.querySelector(".service-icon");
            this.label = clone.querySelector(".label");
            this.update = clone.querySelector(".update");
            this.cancel = clone.querySelector(".cancel");
            this.edit = clone.querySelector(".edit");
            this.explorerLink = clone.querySelector(".explorer-link");
        
            // Attach the created element to the shadow dom
            shadow.appendChild(clone);
        }

        static get observedAttributes() {return ['data-wallet', 'data-address']; }

        attributeChangedCallback(name, oldValue, newValue) {
            if (name=="data-address") {
                this.address = newValue
            }
            if (name=="data-wallet") {
                this.wallet = newValue
            }
            //ToDo: Implement more here
        }

        connectedCallback() {
            this.address = this.getAttribute('data-address');
            this.wallet = this.getAttribute('data-wallet');
            this.labelValue = this.getAttribute('data-label');
            this.serviceId = this.getAttribute('data-service-id');
            this.explorer = '{{ specter.explorer }}';
            this.label.title = this.address;
            this.isEditing = false;

            if ((typeof services !== 'undefined') && (this.serviceId in services)) {
                // `services` globally injected via includes/services-data.html
                this.serviceIconImg.src = "{{ext_url_prefix}}/" + this.serviceId + "/static/" + services[this.serviceId].icon;
            }

            // Set the label - fetch if not specified
            if (this.labelValue) {
                this.label.innerText = this.labelValue;
            } else {
                this.label.innerText = this.address;
                this.fetchAddressLabel();
            }

            // Set title mode for address-label element
            if (this.getAttribute('date-size') == 'title') {
                this.isTitle = true;
                this.label.style.fontSize = '1.5em';
                this.el.style.fontSize = '1.2em';
                this.edit.style.width = '30px';
                this.edit.children[0].style.width = '30px';
                this.explorerLink.style['text-decoration'] = 'none';
            } else {
                this.isTitle = false;
            }

            // Ensure text pasted is not formatted with special formatting.
            this.label.addEventListener('paste', function (event) {
                event.preventDefault();
                document.execCommand('inserttext', false, event.clipboardData.getData('text/plain'));
            });

            this.enableExplorerLink();

            this.edit.onclick = () => {
                this.label.setAttributeNode(document.createAttribute('contenteditable'));
                if (this.isTitle) {
                    this.label.style['font-size'] = '1.1em';
                }
                this.label.style['border-bottom'] = '1px solid #ccc';
                this.labelValue = this.label.innerText;
                this.edit.classList.add('hidden');
                this.cancel.classList.remove('hidden');
                this.update.classList.remove('hidden');
                this.disableExplorerLink();
                this.isEditing = true;
            }

            this.cancel.onclick = () => {
                this.label.innerText = this.labelValue;
                this.closeEditMode();
            }

            this.update.onclick = async () => {
                if (await this.setAddressLabel()) {
                    this.labelValue = this.label.innerText;
                    this.closeEditMode();
                    let event = new CustomEvent('updateAddressLabel', { detail: {
                        label: this.labelValue,
                        address: this.address,
                    }});
                    document.dispatchEvent(event);
                    if (!this.labelValue) {
                        this.label.innerText = this.address
                    }
                } else {
                    showError(`{{ _("Failed to update address label. Please refresh the page and try again.") }}`)
                }
            }
        
            this.addEventListener("updateAddressLabel", function (e) {
                if (this.address != e.detail.address) {
                    return
                }
                this.labelValue = e.detail.label
                if (!this.isEditing) {
                    if (e.detail.label) {
                        this.label.innerText = e.detail.label
                    } else {
                        this.label.innerText = e.detail.address
                    }
                }
            });
        }

        closeEditMode() {
            this.label.removeAttribute('contenteditable')
            if (this.isTitle) {
                this.label.style['font-size'] = '1.5em';
            }
            this.label.style.border = 'none';
            this.edit.classList.remove('hidden');
            this.cancel.classList.add('hidden');
            this.update.classList.add('hidden');
            this.isEditing = false;
            this.enableExplorerLink();
        }

        enableExplorerLink() {
            this.explorerLink.classList.add('explorer-link');
            this.explorerLink.style.removeProperty('text-decoration')
            if (this.explorer) {
                this.explorerLink.href = `${ this.explorer }address/${ this.address }`
                this.explorerLink.onclick = () => {return true;}
            } else {
                this.explorerLink.onclick = () => {
                    copyText(this.address, `{{ _("Copied address") }}: ${ this.address }`);
                }
            }
        }

        disableExplorerLink() {
            this.explorerLink.classList.remove('explorer-link');
            this.explorerLink.removeAttribute('href')
            this.explorerLink.style['text-decoration'] = 'none';
            this.explorerLink.onclick = () => {return false;}
        }

        async fetchAddressLabel() {
            let url = `{{ url_for('wallets_endpoint_api.get_label', wallet_alias='WALLET_ALIAS') }}`.replace("WALLET_ALIAS", this.wallet);
            var formData = new FormData();
            formData.append('address', this.address);
            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;
                }
                const jsonResponse = await response.json();
                if ("label" in jsonResponse) {
                    if (jsonResponse.label) {
                        this.label.innerText = jsonResponse.label;
                    }
                    return;
                }
                showError(`{{ _("Failed to fetch data. Please refresh the page and retry.") }}`);
            } catch(e) {
                console.log(`{{ _("Caught error fetching address label") }}: `, e);
                showError(`{{ _("Failed to fetch data. Please refresh the page and retry.") }}`);
            }
        }

        async setAddressLabel() {
            let url = `{{ url_for('wallets_endpoint_api.set_label', wallet_alias='WALLET_ALIAS') }}`.replace("WALLET_ALIAS", this.wallet);
            var formData = new FormData();
            formData.append('address', this.address);
            formData.append('label', this.label.innerText);
            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;
                }
                const jsonResponse = await response.json();
                return jsonResponse.success;
            } catch(e) {
                console.log("Caught error: ", e);
                showError(e);
                return false;
            }
        }
    }
    customElements.define('address-label', AddressLabelElement);
</script>
