import {Util, Dom} from './util.js';

const dom = new Dom();

class Hyperlink {
    constructor(builder) {

        this.builder = builder;

        const util = new Util(builder);
        const builderStuff = util.builderStuff();
        this.builderStuff = builderStuff;

        // Find or create the link tool
        let linkTool = builderStuff.querySelector('#divLinkTool');
        if (! linkTool) {
            linkTool = this.createLinkTool(util, builderStuff);
        }
        this.linkTool = linkTool;
    }

    /**
     * Handle the element that was clicked.
     */
    click(col, e) {

        // If the column contains custom code, do not show the link tool.
        if (col.hasAttribute('data-html')) {
            this.hideLinkTool();

            return;
        }

        // Get the element that was clicked and reset the active link.
        const elm = e.target;
        this.builder.activeLink = null;

        // If either the element or its parent is not a link, do not show the link tool.
        if (this.elementTagIsNotALink(elm) || ! dom.parentsHasTag(elm, 'a')) {
            this.hideLinkTool();

            return;
        }

        // Sometimes happens when click a link icon, but not exactly on the icon <i>, but the link <a>
        if (elm.childNodes.length > 0
            && elm.childNodes[0].tagName
            && elm.childNodes[0].tagName.toLowerCase() === 'i'
            && elm.childNodes.length === 1
            && elm.childNodes[0].innerHTML === ''
        ) {
            // Remove all active icons
            const icons = document.querySelectorAll('.icon-active');
            Array.prototype.forEach.call(icons, (icon) => {
                dom.removeClass(icon, 'icon-active');
            });

            // Set the first child of the link as active icon
            dom.addClass(elm.childNodes[0], 'icon-active');
            dom.selectElementContents(elm.childNodes[0]);
            this.builder.activeIcon = elm.childNodes[0];
        }

        // If the element is an image
        if (elm.tagName.toLowerCase() === 'img') {
            return;
        }

        // If the element is a link, then set it as the active link otherwise find the link in the parent elements.
        let link;
        if (this.elementTagIsALink(elm)) {
            link = elm;
        } else {
            let element = elm;
            while (this.elementTagIsNotALink(element)) {
                element = element.parentNode;
            }
            link = element;
        }

        this.builder.activeLink = link;
        this.showLinkTool(link);
        e.preventDefault();
    }

    createLinkTool(util, builderStuff) {
        let html = `
            <div id="divLinkTool" class="is-tool">
                <button title="${util.out('Link')}" data-title="${util.out('Link')}" class="link-edit">
                    <svg class="is-icon-flex" style="width:14px;height:14px;">
                        <use xlink:href="#ion-link"></use>
                    </svg>
                </button>
                <button title="${util.out('Duplicate')}" data-title="${util.out('Duplicate')}" class="link-duplicate">
                    <svg class="is-icon-flex" style="width:14px;height:14px;">
                        <use xlink:href="#ion-ios-photos-outline"></use>
                    </svg>
                </button>
                <button title="${util.out('Delete')}" data-title="${util.out('Delete')}" class="link-remove">
                    <svg class="is-icon-flex" style="width:22px;height:22px;">
                        <use xlink:href="#ion-ios-close-empty"></use>
                    </svg>
                </button>
            </div>
        `;
        html += `
            <div class="is-modal createlink">
                <div style="max-width:526px;">    
                                
                    <div class="link-src">
                        <input class="input-url" type="text" placeholder="Url"/>
                        <button title="${util.out('Select')}" class="input-select">
                            <svg class="is-icon-flex">
                                <use xlink:href="#ion-more"></use>
                            </svg>
                        </button>
                    </div>
                    
                    <label style="display:inline-block;margin-top:14px;margin-bottom:10px;float:left;">
                        <input class="input-newwindow" type="checkbox" />  ${util.out('Open New Window')}&nbsp;
                    </label>
                    
                    <input class="input-text" type="text" placeholder="${util.out('Text')}" style="width:100%;"/>
                    <input class="input-title" type="text" placeholder="${util.out('Title')}" style="width:100%;border-top: none;margin-bottom:12px;"/>
                    
                    <div style="text-align:right">
                        <button title="${util.out('Cancel')}" class="input-cancel classic-secondary">
                            ${util.out('Cancel')}
                        </button>
                        <button title="${util.out('Ok')}" class="input-ok classic-primary">
                            ${util.out('Ok')}
                        </button>
                    </div>
                    
                </div>
            </div>
        `;
        html += `
            <div class="is-modal fileselect">
                <div style="max-width:800px;height:80%;padding:0;">
                    <iframe style="width:100%; height:100%; border: none; display: block;" src="about:blank"></iframe>
                </div>
            </div>
        `;
        dom.appendHtml(builderStuff, html);

        let linkTool = builderStuff.querySelector('#divLinkTool');

        // Edit Link
        let linkEdit = linkTool.querySelector('.link-edit');
        dom.addEventListener(linkEdit, 'click', () => { // old: 10853
            this.editLink();
        });

        // Duplicate Link
        let linkDuplicate = linkTool.querySelector('.link-duplicate');
        dom.addEventListener(linkDuplicate, 'click', () => {
            this.duplicateLink();
        });

        // Remove Link
        let linkRemove = linkTool.querySelector('.link-remove');
        dom.addEventListener(linkRemove, 'click', () => {
            this.removeLink(linkTool);
        });

        // Get the modal
        let modal = this.getModal();

        // Save Modal
        let inputOk = modal.querySelector('.input-ok');
        dom.addEventListener(inputOk, 'click', () => {
            this.saveLink(modal, util);
        });

        // Cancel Modal
        let inputCancel = modal.querySelector('.input-cancel');
        dom.addEventListener(inputCancel, 'click', () => {
            util.hideModal(modal);
            if (! util.appleMobile) {
                util.restoreSelection();
            }
        });

        return linkTool;
    }

    showLinkTool(link) {
        // Link tool
        const linkTool = this.linkTool;
        let linkDisplay = dom.getStyle(link, 'display');

        // Handle the duplicate and remove buttons
        if (linkDisplay === 'inline-block') {
            this.showDuplicateLink();
            this.showRemoveLink();

        } else if (this.builder.activeIcon) {
            this.showDuplicateLink();
            this.showRemoveLink();

        } else {
            this.hideDuplicateLink();
            this.hideRemoveLink();
        }

        // Set the position of the link tool
        const top = link.getBoundingClientRect().top;
        const left = link.getBoundingClientRect().left;
        linkTool.style.display = 'flex';

        // to get value, element must not hidden (display:none).
        // So set display:flex before calling this.
        const w = linkTool.offsetWidth;
        const h = linkTool.offsetHeight;
        linkTool.style.top = (top - h + window.pageYOffset - 3) + 'px';
        linkTool.style.left = (left + link.offsetWidth - w) + 'px';
    }
    hideLinkTool() {
        this.linkTool.style.display = '';
    }

    createLink() {
        const util = new Util(this.builder);

        let link;
        if (this.builder.activeLink) {
            link = this.builder.activeLink;

        } else {

            // Adjust selection: If cursor is on existing link, set active link (select the link if it is not icon)
            let elm;
            try {
                let curr;
                if (window.getSelection) {
                    curr = window.getSelection().getRangeAt(0).commonAncestorContainer;
                    if (curr.nodeType === 3) {  //text node
                        elm = curr.parentNode;
                    } else {
                        elm = curr;
                    }
                } else if (document.selection) {
                    curr = document.selection.createRange();
                    elm = document.selection.createRange().parentElement();
                }
            } catch (e) {
                return;
            }

            // If the element is a link, then set it as the active link, otherwise find the link in the parent elements.
            if (this.elementNodeIsALink(elm)) {
                link = elm;
            } else {
                let element = elm;
                while (this.elementNodeIsNotALink(element)) {
                    if (this.elementTagIsBody(element) || this.elementTagIsHtml(element)) {
                        break;
                    }
                    if (element.parentNode) {
                        element = element.parentNode;
                    }
                }
                if (this.elementNodeIsALink(element)) {
                    link = element;
                }
            }

            // Set active link
            if (link) {
                this.builder.activeLink = link;

                // Select the link if it is not icon or empty
                if (! this.elementNodeIsIcon(elm) && ! this.elementIsEmpty(elm)) {
                    dom.selectElementContents(this.builder.activeLink);
                    util.saveSelection();
                }
            }
        }

        // Get the selected text
        let text = dom.getSelected();

        // Find the create link modal
        let modal = this.getModal();

        // If the builder has a file select function, show the file select button
        this.checkIfFileSelectionIsEnabled(modal, util);

        // Reset values
        this.resetModalUrlField(modal);
        this.resetModalNewWindowField(modal);
        this.resetModalTitleField(modal);
        this.resetModalTextField(modal);

        if (link) {
            this.setModalUrlField(modal, link.href.toLowerCase());

            link.target === '_blank'
                ? this.setModalNewWindowField(modal, true)
                : this.setModalNewWindowField(modal, false);

            this.setModalTitleField(modal, link.title);
            this.setModalTextField(modal, link.innerHTML);

        } else {
            this.setModalTextField(modal, text);
        }

        // Show modal
        let cancelCallback = function () {
            if (! util.appleMobile) {
                util.restoreSelection();
            }
        }
        util.showModal(modal, true, cancelCallback, true);

        // Focus the url field
        this.focusModalUrlField(modal);
    }
    editLink() {
        const util = new Util(this.builder);

        let link = this.builder.activeLink;

        // Find the create link modal
        let modal = this.getModal();

        // If the builder has a file select function, show the file select button
        this.checkIfFileSelectionIsEnabled(modal, util);

        // Set the values from the link
        this.setModalUrlField(modal, link.getAttribute('href').toLowerCase());

        link.getAttribute('target') === '_blank'
            ? this.setModalNewWindowField(modal, true)
            : this.setModalNewWindowField(modal, false);

        this.setModalTitleField(modal, link.getAttribute('title'));
        this.setModalTextField(modal, link.innerHTML);

        // Show modal
        util.showModal(modal, true, null, true);

        // Focus the url field
        this.focusModalUrlField(modal);
    }
    saveLink(modal, util) {
        this.builder.uo.saveForUndo();

        let link = this.builder.activeLink;
        if (link) {

            // Edit Existing Link
            let url = this.getModalUrlField(modal).value.toLowerCase();
            let title = this.getModalTitleField(modal).value;
            let linkText = this.getModalTextField(modal).value;

            // If there is no link text use the url
            if (linkText === '') {
                linkText = url;
            }

            // If the url is not empty
            if (url !== '') {
                link.setAttribute('href', url);

                if (this.getModalNewWindowField(modal).checked) {
                    link.setAttribute('target', '_blank');
                } else {
                    link.removeAttribute('target');
                }

                // If the link is not an icon, then replace the contents
                if (! this.builder.activeIcon) {
                    link.innerHTML = linkText;
                }

                link.setAttribute('title', title);

            } else {
                dom.selectElementContents(link);
                document.execCommand('unlink', false, null);
            }

            // Trigger Change event
            this.builder.opts.onChange();

        } else {
            // Create New Link
            util.restoreSelection();

            let url = this.getModalUrlField(modal).value.toLowerCase();
            let title = this.getModalTitleField(modal).value;
            let linkText = this.getModalTextField(modal).value;

            // If there is no link text use the url
            if (linkText === '') {
                linkText = url;
            }

            // If the url is not empty
            if (url !== '') {
                this.builder.uo.saveForUndo();

                let activeLink;
                if (this.builder.activeIcon) { // Icon is selected

                    let iconHtml = this.builder.activeIcon.outerHTML;
                    this.builder.activeIcon.outerHTML = `<a class="__dummy" href="${url}">${iconHtml}</a>`;
                    activeLink = document.querySelector('.__dummy');
                    dom.removeClass(activeLink, '__dummy');

                    if (this.getModalNewWindowField(modal).checked) {
                        activeLink.setAttribute('target', '_blank');
                    } else {
                        activeLink.removeAttribute('target');
                    }

                    activeLink.setAttribute('title', title);

                    this.builder.activeIcon = activeLink.childNodes[0];

                    if (! util.appleMobile) dom.selectElementContents(this.builder.activeIcon);

                } else {
                    document.execCommand('createLink', false, 'http://dummy');
                    let activeLink = document.querySelector('a[href="http://dummy"]');
                    activeLink.setAttribute('href', url);

                    activeLink.innerHTML = linkText;

                    if (this.getModalNewWindowField(modal).checked) {
                        activeLink.setAttribute('target', '_blank');
                    } else {
                        activeLink.removeAttribute('target');
                    }

                    activeLink.setAttribute('title', title);

                    if (! util.appleMobile) {
                        dom.selectElementContents(activeLink);
                    }
                }

            }

            // save selection
            util.saveSelection();

            // Trigger Change event
            this.builder.opts.onChange();

            // Trigger Render event
            this.builder.opts.onRender();
        }

        util.hideModal(modal);
    }
    duplicateLink() {
        // If there is no active link then bail
        if (! this.builder.activeLink) {
            return;
        }

        this.builder.uo.saveForUndo();

        // Is the builder in email editor mode
        if (this.builder.opts.emailMode) {
            let element = this.builder.activeLink;
            while (element.tagName.toLowerCase() !== 'table' && ! dom.hasClass(element, 'button')) {
                element = element.parentNode;
            }
            element = element.parentNode;

            let activeLinkTD = element;
            const newLinkTD = activeLinkTD.cloneNode(true);

            // if there is active icon class, do not copy the class
            let iconActive = newLinkTD.querySelector('.icon-active');
            if (iconActive) {
                dom.removeClass(iconActive, 'icon-active');
            }

            newLinkTD.style.paddingRight = '15px';
            activeLinkTD.parentNode.insertBefore(newLinkTD, activeLinkTD);

            this.showLinkTool(this.builder.activeLink);

            return;
        }

        // Otherwise this is the web builder
        const newLink = this.builder.activeLink.cloneNode(true);

        // if there is active icon class, do not copy the class
        let iconActive = newLink.querySelector('.icon-active');
        if (iconActive) {
            dom.removeClass(iconActive, 'icon-active');
        }

        this.builder.activeLink.parentNode.insertBefore(newLink, this.builder.activeLink);

        this.showLinkTool(this.builder.activeLink);
    }
    removeLink(linkTool) {
        this.builder.uo.saveForUndo();

        if (this.builder.opts.emailMode) {
            let element = this.builder.activeLink;
            while (element.tagName.toLowerCase() !== 'table' && ! dom.hasClass(element, 'button')) {
                element = element.parentNode;
            }
            element = element.parentNode;
            let activeLinkTD = element;

            if (activeLinkTD) {
                activeLinkTD.parentNode.removeChild(activeLinkTD);
            }
            linkTool.style.display = '';

        } else {
            if (this.builder.activeLink) {
                this.builder.activeLink.parentNode.removeChild(this.builder.activeLink);
            }
            linkTool.style.display = '';
        }

        // if there is active icon, set null.
        let iconActive = this.builder.activeLink.querySelector('.icon-active');
        if (iconActive) {
            this.builder.activeIcon = null;
        }
    }

    checkIfFileSelectionIsEnabled(modal, util) {
        if (this.builder.opts.onFileSelectClick || this.builder.opts.fileselect !== '') {
            this.showSelectFileBtn(modal);
            this.setModalUrlFieldWidth(modal, '444px');
            this.handleSelectFileEvent(modal, util);

            return;

        }

        this.hideSelectFileBtn(modal);
        this.setModalUrlFieldWidth(modal, '100%');
    }

    getModal() {
        return this.builderStuff.querySelector('.is-modal.createlink');
    }
    getModalUrlField(modal) {
        return modal.querySelector('.input-url');
    }
    setModalUrlField(modal, value) {
        this.getModalUrlField(modal).value = value;
    }
    setModalUrlFieldWidth(modal, value) {
        this.getModalUrlField(modal).style.width = value;
    }
    focusModalUrlField(modal) {
        this.getModalUrlField(modal).focus();
    }
    resetModalUrlField(modal) {
        this.setModalUrlField(modal, '');
    }

    getModalNewWindowField(modal) {
        return modal.querySelector('.input-newwindow');
    }
    setModalNewWindowField(modal, value) {
        this.getModalNewWindowField(modal).checked = value;
    }
    resetModalNewWindowField(modal) {
        this.setModalNewWindowField(modal, false);
    }

    getModalTextField(modal) {
        return modal.querySelector('.input-text');
    }
    setModalTextField(modal, value) {
        this.getModalTextField(modal).value = value;
    }
    resetModalTextField(modal) {
        this.setModalTextField(modal, '');
    }

    getModalTitleField(modal) {
        return modal.querySelector('.input-title');
    }
    setModalTitleField(modal, value) {
        this.getModalTitleField(modal).value = value;
    }
    resetModalTitleField(modal) {
        this.setModalTitleField(modal, '');
    }

    showSelectFileBtn(modal) {
        modal.querySelector('.input-select').style.display = 'block';
    }
    hideSelectFileBtn(modal) {
        modal.querySelector('.input-select').style.display = 'none';
    }
    handleSelectFileEvent(modal, util) {
        let inputSelect = modal.querySelector('.input-select');

        dom.addEventListener(inputSelect, 'click', (e) => {

            if (this.builder.opts.onFileSelectClick) {
                this.builder.opts.onFileSelectClick({
                    targetInput : modal.querySelector('.input-url'),
                    theTrigger : modal.querySelector('.input-select')
                });

            } else {
                let modalFileSelect = this.builderStuff.querySelector('.is-modal.fileselect');
                if (modalFileSelect.querySelector('iframe').src === 'about:blank') {
                    modalFileSelect.querySelector('iframe').src = this.builder.opts.fileselect;
                }
                util.showModal(modalFileSelect, false, null, false);
            }

            e.preventDefault();
            e.stopImmediatePropagation();
        });
    }

    elementIsEmpty(elm) {
        return elm.innerHTML === '';
    }

    elementTagIsALink(element) {
        return element.tagName.toLowerCase() === 'a';
    }
    elementTagIsNotALink(element) {
        return element.tagName.toLowerCase() !== 'a';
    }
    elementTagIsHtml(element) {
        return element.tagName === 'HTML';
    }
    elementTagIsBody(element) {
        return element.tagName === 'BODY';
    }

    elementNodeIsALink(element) {
        return element.nodeName.toLowerCase() === 'a';
    }
    elementNodeIsNotALink(element) {
        return element.nodeName.toLowerCase() !== 'a';
    }
    elementNodeIsIcon(element) {
        return element.nodeName.toLowerCase() === 'i';
    }

    showRemoveLink() {
        this.linkTool.querySelector('.link-remove').style.display = 'block';
    }
    hideRemoveLink() {
        this.linkTool.querySelector('.link-remove').style.display = 'none';
    }
    showDuplicateLink() {
        this.linkTool.querySelector('.link-duplicate').style.display = 'block';
    }
    hideDuplicateLink() {
        this.linkTool.querySelector('.link-duplicate').style.display = 'none';
    }
}

export default Hyperlink;