import { IAccessibility } from './interfaces/accessibility.interface';
import { IMenuInterface } from './interfaces/menu.interface';

export class MenuInterface implements IMenuInterface {
    private _acc: IAccessibility;
    private readBind: any;
    private _dialog: HTMLDialogElement;
    constructor(accessibility: IAccessibility) {
        this._acc = accessibility;
        this.readBind = this._acc.read.bind(this._acc);
    }

    increaseText() {
        this._acc.alterTextSize(true);
    }

    decreaseText() {
        this._acc.alterTextSize(false);
    }

    increaseTextSpacing() {
        this._acc.alterTextSpace(true);
    }

    decreaseTextSpacing() {
        this._acc.alterTextSpace(false);
    }

    invertColors(destroy: boolean) {
        if (typeof this._acc.stateValues.html.backgroundColor === 'undefined')
            this._acc.stateValues.html.backgroundColor = getComputedStyle(this._acc.html).backgroundColor;
        if (typeof this._acc.stateValues.html.color === 'undefined')
            this._acc.stateValues.html.color = getComputedStyle(this._acc.html).color;

        if (destroy) {
            this._acc.resetIfDefined(this._acc.stateValues.html.backgroundColor, this._acc.html.style, 'backgroundColor');
            this._acc.resetIfDefined(this._acc.stateValues.html.color, this._acc.html.style, 'color');
            if (!this._acc.options.suppressDomInjection)
                document.querySelector('._access-menu [data-access-action="invertColors"]').classList.remove('active');
            this._acc.stateValues.invertColors = false;
            this._acc.sessionState.invertColors = this._acc.stateValues.invertColors;
            this._acc.onChange(true);
            this._acc.html.style.filter = '';
            return;
        }

        if (this._acc.stateValues.invertColors && this._acc.stateValues.textToSpeech) {
            this._acc.textToSpeech('Colors Set To Normal');
        }
        if (!this._acc.options.suppressDomInjection)
            document.querySelector('._access-menu [data-access-action="invertColors"]').classList.toggle('active');
        this._acc.stateValues.invertColors = !this._acc.stateValues.invertColors;
        this._acc.sessionState.invertColors = this._acc.stateValues.invertColors;
        this._acc.onChange(true);
        if (this._acc.stateValues.invertColors) {
            if (this._acc.stateValues.grayHues)
                this._acc.menuInterface.grayHues(true);
            this._acc.html.style.filter = 'invert(1)';

            if (this._acc.stateValues.textToSpeech) {
                this._acc.textToSpeech('Colors Inverted');
            }
        }
        else {
            this._acc.html.style.filter = '';
        }
    }

    grayHues(destroy: boolean) {
        if (typeof this._acc.stateValues.html.filter === 'undefined')
            this._acc.stateValues.html.filter = getComputedStyle(this._acc.html).filter;
        if (typeof this._acc.stateValues.html.webkitFilter === 'undefined')
            this._acc.stateValues.html.webkitFilter = getComputedStyle(this._acc.html).webkitFilter;
        if (typeof this._acc.stateValues.html.mozFilter === 'undefined')
            this._acc.stateValues.html.mozFilter = (getComputedStyle(this._acc.html) as any).mozFilter;
        if (typeof this._acc.stateValues.html.msFilter === 'undefined')
            this._acc.stateValues.html.msFilter = (getComputedStyle(this._acc.html) as any).msFilter;

        if (destroy) {
            if (!this._acc.options.suppressDomInjection)
                document.querySelector('._access-menu [data-access-action="grayHues"]').classList.remove('active');
            this._acc.stateValues.grayHues = false;
            this._acc.sessionState.grayHues = this._acc.stateValues.grayHues;
            this._acc.onChange(true);
            this._acc.resetIfDefined(this._acc.stateValues.html.filter, this._acc.html.style, 'filter');
            this._acc.resetIfDefined(this._acc.stateValues.html.webkitFilter, this._acc.html.style, 'webkitFilter');
            this._acc.resetIfDefined(this._acc.stateValues.html.mozFilter, this._acc.html.style, 'mozFilter');
            this._acc.resetIfDefined(this._acc.stateValues.html.msFilter, this._acc.html.style, 'msFilter');
            return;
        }

        if (!this._acc.options.suppressDomInjection)
            document.querySelector('._access-menu [data-access-action="grayHues"]').classList.toggle('active');
        this._acc.stateValues.grayHues = !this._acc.stateValues.grayHues;
        this._acc.sessionState.grayHues = this._acc.stateValues.grayHues;
        this._acc.onChange(true);
        if (this._acc.stateValues.textToSpeech && !this._acc.stateValues.grayHues)
            this._acc.textToSpeech('Gray Hues Disabled.');
        let val;
        if (this._acc.stateValues.grayHues) {
            val = 'grayscale(1)';
            if (this._acc.stateValues.invertColors) {
                this.invertColors(true);
            }
            if (this._acc.stateValues.textToSpeech) {
                this._acc.textToSpeech('Gray Hues Enabled.');
            }
        } else {
            val = '';
        }
        this._acc.html.style.webkitFilter = val;
        (this._acc.html.style as any).mozFilter = val;
        (this._acc.html.style as any).msFilter = val;
        this._acc.html.style.filter = val;
    }

    underlineLinks(destroy: boolean) {
        let className = '_access-underline';
        let remove = () => {
            let style = document.querySelector('.' + className);
            if (style) {
                style.parentElement.removeChild(style);
                this._acc.common.deployedObjects.remove('.' + className);
            }
        };

        if (destroy) {
            this._acc.stateValues.underlineLinks = false;
            this._acc.sessionState.underlineLinks = this._acc.stateValues.underlineLinks;
            this._acc.onChange(true);
            if (!this._acc.options.suppressDomInjection)
                document.querySelector('._access-menu [data-access-action="underlineLinks"]').classList.remove('active');
            return remove();
        }

        if (!this._acc.options.suppressDomInjection)
            document.querySelector('._access-menu [data-access-action="underlineLinks"]').classList.toggle('active');
        this._acc.stateValues.underlineLinks = !this._acc.stateValues.underlineLinks;
        this._acc.sessionState.underlineLinks = this._acc.stateValues.underlineLinks;
        this._acc.onChange(true);
        if (this._acc.stateValues.underlineLinks) {
            let css = `
            body a {
                text-decoration: underline !important;
            }
        `;
            this._acc.common.injectStyle(css, { className: className });
            this._acc.common.deployedObjects.set('.' + className, true);
            if (this._acc.stateValues.textToSpeech) {
                this._acc.textToSpeech('Links UnderLined');
            }
        }
        else {
            if (this._acc.stateValues.textToSpeech) {
                this._acc.textToSpeech('Links UnderLine Removed');
            }
            remove();
        }
    }

    bigCursor(destroy: boolean) {
        if (destroy) {
            this._acc.html.classList.remove('_access_cursor');
            if (!this._acc.options.suppressDomInjection)
                document.querySelector('._access-menu [data-access-action="bigCursor"]').classList.remove('active');
            this._acc.stateValues.bigCursor = false;
            this._acc.sessionState.bigCursor = false;
            this._acc.onChange(true);
            return;
        }

        if (!this._acc.options.suppressDomInjection)
            document.querySelector('._access-menu [data-access-action="bigCursor"]').classList.toggle('active');
        this._acc.stateValues.bigCursor = !this._acc.stateValues.bigCursor;
        this._acc.sessionState.bigCursor = this._acc.stateValues.bigCursor;
        this._acc.onChange(true);
        this._acc.html.classList.toggle('_access_cursor');
        if (this._acc.stateValues.textToSpeech && this._acc.stateValues.bigCursor) this._acc.textToSpeech('Big Cursor Enabled');
        if (this._acc.stateValues.textToSpeech && !this._acc.stateValues.bigCursor) this._acc.textToSpeech('Big Cursor Disabled');
    }

    readingGuide(destroy: boolean) {
        if (destroy) {
            if (document.getElementById('access_read_guide_bar')) {
                document.getElementById('access_read_guide_bar').remove();
            }
            if (!this._acc.options.suppressDomInjection)
                document.querySelector('._access-menu [data-access-action="readingGuide"]').classList.remove('active');
            this._acc.stateValues.readingGuide = false;
            this._acc.sessionState.readingGuide = this._acc.stateValues.readingGuide;
            this._acc.onChange(true);
            document.body.removeEventListener('touchmove', this._acc.updateReadGuide, false);
            document.body.removeEventListener('mousemove', this._acc.updateReadGuide, false);
            if (this._acc.stateValues.textToSpeech) this._acc.textToSpeech('Reading Guide Enabled');
            return;
        }
        if (!this._acc.options.suppressDomInjection)
            document.querySelector('._access-menu [data-access-action="readingGuide"]').classList.toggle('active');
        this._acc.stateValues.readingGuide = !this._acc.stateValues.readingGuide;
        this._acc.sessionState.readingGuide = this._acc.stateValues.readingGuide;
        this._acc.onChange(true);
        if (this._acc.stateValues.readingGuide) {
            let read = document.createElement('div');
            read.id = 'access_read_guide_bar';
            read.classList.add('access_read_guide_bar');
            document.body.append(read);
            document.body.addEventListener('touchmove', this._acc.updateReadGuide, false);
            document.body.addEventListener('mousemove', this._acc.updateReadGuide, false);
        } else {
            if (document.getElementById('access_read_guide_bar') !== undefined) {
                document.getElementById('access_read_guide_bar').remove();
            }
            document.body.removeEventListener('touchmove', this._acc.updateReadGuide, false);
            document.body.removeEventListener('mousemove', this._acc.updateReadGuide, false);
            if (this._acc.stateValues.textToSpeech) this._acc.textToSpeech('Reading Guide Disabled');
        }
    }

    textToSpeech(destroy: boolean) {
        // this.sessionState.textToSpeech = typeof destroy === 'undefined' ? true : false;
        const tSpeechList = document.querySelector('._access-menu [data-access-action="textToSpeech"]');
        if (!tSpeechList) return;

        let step1 = document.getElementsByClassName('screen-reader-wrapper-step-1');
        let step2 = document.getElementsByClassName('screen-reader-wrapper-step-2');
        let step3 = document.getElementsByClassName('screen-reader-wrapper-step-3');
        this._acc.onChange(false);
        const className = '_access-text-to-speech';
        let remove = () => {
            let style = document.querySelector('.' + className);
            if (style) {
                style.parentElement.removeChild(style);
                document.removeEventListener('click', this.readBind, false);
                document.removeEventListener('keyup', this.readBind, false);
                this._acc.common.deployedObjects.remove('.' + className);
            }
            if (window.speechSynthesis)
                window.speechSynthesis.cancel();
            this._acc.isReading = false;
        };

        if (destroy) {
            tSpeechList.classList.remove('active');
            step1[0].classList.remove('active');
            step2[0].classList.remove('active');
            step3[0].classList.remove('active');
            this._acc.stateValues.textToSpeech = false;
            window.speechSynthesis.cancel();
            return remove();
        }

        if (this._acc.stateValues.speechRate === 1 && !tSpeechList.classList.contains('active')) {
            this._acc.stateValues.textToSpeech = true;
            this._acc.textToSpeech('Screen Reader enabled. Reading Pace - Normal');
            tSpeechList.classList.add('active');
            step1[0].classList.add('active');
            step2[0].classList.add('active');
            step3[0].classList.add('active');
        }
        else if (this._acc.stateValues.speechRate === 1 && tSpeechList.classList.contains('active')) {
            this._acc.stateValues.speechRate = 1.5;
            this._acc.textToSpeech('Reading Pace - Fast');
            step1[0].classList.remove('active');
        }
        else if (this._acc.stateValues.speechRate === 1.5 && tSpeechList.classList.contains('active')) {
            this._acc.stateValues.speechRate = 0.7;
            this._acc.textToSpeech('Reading Pace - Slow');
            step2[0].classList.remove('active');
        } else {
            this._acc.stateValues.speechRate = 1;
            this._acc.textToSpeech('Screen Reader - Disabled');
            tSpeechList.classList.remove('active');
            step3[0].classList.remove('active');

            let timeout: ReturnType<typeof setInterval> = setInterval(() => {
                if (this._acc.isReading) {
                    return;
                }
                this._acc.stateValues.textToSpeech = false;

                remove();
                clearTimeout(timeout);
            }, 500);

            return;
        }

        let css = `
            *:hover {
                box-shadow: 2px 2px 2px rgba(180,180,180,0.7);
            }
        `;

        if (tSpeechList.classList.contains('active') && this._acc.stateValues.speechRate === 1) {
            this._acc.common.injectStyle(css, { className: className });
            this._acc.common.deployedObjects.set('.' + className, true);
            document.addEventListener('click', this.readBind, false);
            document.addEventListener('keyup', this.readBind, false);
        }
    }

    speechToText(destroy: boolean) {
        // this.sessionState.speechToText = typeof destroy === 'undefined' ? true : false;
        const sTextList = document.querySelector('._access-menu [data-access-action="speechToText"]');
        if (!sTextList) return;

        this._acc.onChange(false);
        let className = '_access-speech-to-text';
        let remove = () => {
            if (this._acc.recognition) {
                this._acc.recognition.stop();
                this._acc.body.classList.remove('_access-listening');
            }
            let style = document.querySelector('.' + className);
            if (style) {
                style.parentElement.removeChild(style);
                this._acc.common.deployedObjects.remove('.' + className);
            }
            let inputs = document.querySelectorAll('._access-mic');
            for (let i = 0; i < inputs.length; i++) {
                inputs[i].removeEventListener('focus', this._acc.listen.bind(this._acc), false);
                inputs[i].classList.remove('_access-mic');
            }
            sTextList.classList.remove('active');
        };

        if (destroy) {
            this._acc.stateValues.speechToText = false;
            return remove();
        }

        this._acc.stateValues.speechToText = !this._acc.stateValues.speechToText;
        if (this._acc.stateValues.speechToText) {
            let css = `
                body:after {
                    content: ${!this._acc.options.icon.useEmojis ? '"mic"' : 'var(--_access-menu-item-icon-mic,"🎤")'};
                    ${!this._acc.options.icon.useEmojis ? `font-family: var(--_access-menu-item-icon-font-family-after, ${this._acc.fixedDefaultFont}` : ''}
                    position: fixed;
                    z-index: 1100;
                    top: 1vw;
                    right: 1vw;
                    width: 36px;
                    height: 36px;
                    font-size: 30px;
                    line-height: 36px;
                    border-radius: 50%;
                    background: rgba(255,255,255,0.7);
                    display: flex;
                    justify-content: center;
                    aling-items: center;
                }

                body._access-listening:after {
                    animation: _access-listening-animation 2s infinite ease;
                }

                @keyframes _access-listening-animation {
                    0%  {background-color: transparent;}
                    50%  {background-color: #EF9A9A;}
                }
            `;
            this._acc.common.injectStyle(css, { className: className });
            this._acc.common.deployedObjects.set('.' + className, true);
            let inputs = document.querySelectorAll('input[type="text"], input[type="email"], input[type="tel"], input[type="search"], textarea, [contenteditable]');
            for (let i = 0; i < inputs.length; i++) {
                inputs[i].addEventListener('blur', () => {
                    if (typeof this._acc.recognition === 'object' && typeof this._acc.recognition.stop === 'function')
                        this._acc.recognition.stop();
                }, false);
                inputs[i].addEventListener('focus', this._acc.listen.bind(this._acc), false);
                inputs[i].parentElement.classList.add('_access-mic');
            }
            sTextList.classList.add('active');
        }
        else
            remove();
    }

    disableAnimations(destroy: boolean) {
        const className = '_access-disable-animations', autoplayStopped = 'data-autoplay-stopped';

        const remove = () => {
            if (!this._acc.options.suppressDomInjection)
                document.querySelector('._access-menu [data-access-action="disableAnimations"]').classList.remove('active');
            this._acc.stateValues.disableAnimations = false;
            let style = document.querySelector('.' + className);
            if (style) {
                style.parentElement.removeChild(style);
                this._acc.common.deployedObjects.remove('.' + className);
            }
            let allImages = document.querySelectorAll('[data-org-src]') as NodeListOf<HTMLImageElement>;
            allImages.forEach(async i => {
                const screenshot = i.src;
                i.setAttribute('src', i.getAttribute('data-org-src'));
                i.setAttribute('data-org-src', screenshot);
            });
            const allVideos = document.querySelectorAll(`video[${autoplayStopped}]`) as NodeListOf<HTMLVideoElement>;
            allVideos.forEach(v => {
                v.setAttribute('autoplay', '');
                v.removeAttribute(autoplayStopped);
                v.play();
            });
        };
        if (destroy) {
            remove();
            return;
        }
        this._acc.stateValues.disableAnimations = !this._acc.stateValues.disableAnimations;
        if (!this._acc.stateValues.disableAnimations) {
            remove();
            return;
        }

        if (!this._acc.options.suppressDomInjection)
            document.querySelector('._access-menu [data-access-action="disableAnimations"]').classList.add('active');
        let css = `
                body * {
                    animation-duration: 0.0ms !important;
                    transition-duration: 0.0ms !important;
                }
        `;
        this._acc.common.injectStyle(css, { className: className });
        this._acc.common.deployedObjects.set('.' + className, true);
        const allImages = document.querySelectorAll('img');
        allImages.forEach(async i => {
            let ext = this._acc.common.getFileExtension(i.src);
            if (ext && ext.toLowerCase() === 'gif') {
                let screenshot = i.getAttribute('data-org-src');
                if (!screenshot)
                    screenshot = await this._acc.common.createScreenshot(i.src);
                i.setAttribute('data-org-src', i.src);
                i.src = screenshot;
            }
        });
        const allVideos = document.querySelectorAll('video[autoplay]') as NodeListOf<HTMLVideoElement>;
        allVideos.forEach(v => {
            v.setAttribute(autoplayStopped, '');
            v.removeAttribute('autoplay');
            v.pause();
        });
    }

    iframeModals(destroy?: boolean, button?: HTMLElement) {
        if (!button)
            destroy = true;
        const close = () => {
            if (this._dialog) {
                this._dialog.classList.add('closing');
                setTimeout(() => {
                    this._dialog.classList.remove('closing');
                    this._dialog.close();
                    this._dialog.remove();
                }, 350);
                detach();
            }
            if (button)
                button.classList.remove('active');
        };
        const onClose = () => {
            close();
        };
        const detach = () => {
            this._dialog.querySelector('button').removeEventListener('click', onClose, false);
            this._dialog.removeEventListener('close', onClose);
        };
        if (destroy) {
            close();
        }
        else {
            button.classList.add('active');
            if (!this._dialog)
                this._dialog = document.createElement('dialog');
            this._dialog.classList.add('_access');
            this._dialog.innerHTML = '';
            this._dialog.appendChild(this._acc.common.jsonToHtml({
                type: 'div',
                children: [
                    {
                        type: 'div',
                        children: [
                            {
                                type: 'button',
                                attrs: {
                                    role: 'button',
                                    'class': this._acc.options.icon.useEmojis ? '' : this._acc.options.icon.fontClass,
                                    style: `position: absolute;
                                    top: 5px;
                                    cursor: pointer;
                                    font-size: 24px !important;
                                    font-weight: bold;
                                    background: transparent;
                                    border: none;
                                    left: 5px;
                                    color: #d63c3c;
                                    padding: 0;`
                                },
                                children: [
                                    {
                                        type: '#text',
                                        text: this._acc.options.icon.useEmojis ? 'X' : 'close'
                                    }
                                ]
                            }
                        ]
                    },
                    {
                        type: 'div',
                        children: [
                            {
                                type: 'iframe',
                                attrs: {
                                    src: button.getAttribute('data-access-url'),
                                    style: 'width: 50vw;height: 50vh;padding: 30px;'
                                }
                            }
                        ]
                    }
                ]
            }));
            document.body.appendChild(this._dialog);
            this._dialog.querySelector('button').addEventListener('click', onClose, false);
            this._dialog.addEventListener('close', onClose);
            this._dialog.showModal();
        }
    }

    customFunctions(destroy?: boolean, button?: HTMLElement) {
        if (!button)
            return;
        const cf = this._acc.options.customFunctions[parseInt(button.getAttribute('data-access-custom-index'))];
        if (cf.toggle && button.classList.contains('active'))
            destroy = true;
        if (destroy) {
            if (cf.toggle)
                button.classList.remove('active');
            cf.method(cf, false);
        }
        else {
            if (cf.toggle)
                button.classList.add('active');
            cf.method(cf, true);
        }
    }

    increaseLineHeight() {
        this._acc.alterLineHeight(true);
    }

    decreaseLineHeight() {
        this._acc.alterLineHeight(false);
    }
}