import "@webcomponents/webcomponentsjs";
import { browser } from "webextension-polyfill-ts";
// import { throttle } from "@padloc/core/src/util";
import { Message } from "./message";

const css = `
    @font-face {
        font-family: "Nunito";
        font-style: normal;
        font-weight: 400;
        src: url("${browser.runtime.getURL("Nunito-Regular.ttf")}") format("truetype");
    }

    @font-face {
        font-family: "Nunito";
        font-style: normal;
        font-weight: 600;
        src: url("${browser.runtime.getURL("Nunito-SemiBold.ttf")}") format("truetype");
    }

    @font-face {
        font-family: "FontAwesome";
        src: url("${browser.runtime.getURL("fontawesome-webfont.ttf")}") format("truetype");
        font-weight: normal;
        font-style: normal;
    }

    @keyframes ripple {
        from {
            opacity: 0.3;
            transform: scale(1);
        }

        to {
            opacity: 0;
            transform: scale(2);
        }
    }

    @keyframes highlight {
        from {
            opacity: 0;
            transform: scale(1.1);
        }

        to {
            opacity: 1;
            transform: scale(1);
        }
    }

    .ripple {
        position: absolute;
        z-index: 9999999;
        border-radius: 8px;
        background: #3bb7f9;
        animation: ripple 0.8s both;
        pointer-events: none;
        will-change: transform, opacity;
    }

    .highlight {
        position: absolute;
        left: 0;
        top: 0;
        z-index: 9999999;
        border-radius: 8px;
        border: solid 2px #3bb7f9;
        box-sizing: border-box;
        pointer-events: none;
        will-change: transform, width, height, opacity;
        animation: highlight 0.3s both;
    }

    .highlight.out {
        animation-direction: reverse;
    }

    .drag-element {
        position: absolute;
        top: 0;
        left: 0;
        z-index: 9999999;
        border-radius: 8px;
        background: #3bb7f9;
        color: white;
        padding: 6px;
        cursor: grabbing;
        will-change: transform;
        font-family: "Nunito";
        font-size: 14px;
    }

    body.dragging {
        cursor: grabbing !important;
    }
`;

class ExtensionContent {
    // private _hoveredInput: HTMLInputElement | null = null;
    //
    // private _highlightElement: HTMLDivElement;

    async init() {
        const style = document.createElement("style");
        document.head.appendChild(style);
        style.type = "text/css";
        style.appendChild(document.createTextNode(css));
        browser.runtime.onMessage.addListener((msg: Message) => this._handleMessage(msg));
    }

    private _handleMessage(msg: Message) {
        switch (msg.type) {
            case "fillActive":
                // console.log("autofill", msg);
                return Promise.resolve(this._fill(msg.value));
            // case "fillOnDrop":
            //     // console.log("autofill", msg);
            //     return new Promise(resolve => {
            //         let timeout: number;
            //
            //         const dragover = (e: DragEvent) => {
            //             // console.log("dragover", performance.now());
            //             if (timeout) {
            //                 clearTimeout(timeout);
            //             }
            //             this._updateHovered(e);
            //         };
            //
            //         const dragleave = () => {
            //             // console.log("dragleave", performance.now());
            //             timeout = window.setTimeout(() => {
            //                 if (this._hoveredInput) {
            //                     resolve(this._fill(msg.value, this._hoveredInput));
            //                 } else {
            //                     resolve(false);
            //                 }
            //
            //                 this._highlight(null);
            //                 this._hoveredInput = null;
            //                 document.removeEventListener("dragover", dragover);
            //                 document.removeEventListener("dragleave", dragleave);
            //             }, 100);
            //         };
            //
            //         document.addEventListener("dragover", dragover);
            //         document.addEventListener("dragleave", dragleave);
            //     });
            case "hasActiveInput":
                const activeInput = this._getActiveInput();
                // console.log("has active input", activeInput);
                return Promise.resolve(!!activeInput);
            case "isContentReady":
                return Promise.resolve(true);
        }
    }

    private _getActiveElement(doc: DocumentOrShadowRoot): Element | null {
        const el = doc.activeElement;
        return (el && el.shadowRoot && this._getActiveElement(el.shadowRoot)) || el;
    }

    private _isElementFillable(el: Element) {
        return (
            el instanceof HTMLInputElement &&
            ["text", "number", "email", "password", "tel", "date", "month", "search", "url"].includes(el.type)
        );
    }

    private _getActiveInput(): HTMLInputElement | null {
        const el = this._getActiveElement(document);
        return el && this._isElementFillable(el) ? (el as HTMLInputElement) : null;
    }

    private async _fill(value: string, input: HTMLInputElement | null = this._getActiveInput()) {
        if (!input) {
            return false;
        }

        input.value = value;

        // Do some song and dance for various frameworks that expect input events
        input.dispatchEvent(
            new KeyboardEvent("keydown", {
                bubbles: true,
                key: "",
            })
        );
        input.dispatchEvent(
            new KeyboardEvent("keyup", {
                bubbles: true,
                key: "",
            })
        );
        input.dispatchEvent(
            new KeyboardEvent("keypress", {
                bubbles: true,
                key: "",
            })
        );
        input.dispatchEvent(new Event("input", { bubbles: true }));
        input.dispatchEvent(new Event("change", { bubbles: true }));
        // this._ripple(input);
        return true;
    }

    // private _ripple(el: HTMLElement) {
    //     const { left, top, width, height } = el.getBoundingClientRect();
    //     const ripple = document.createElement("div");
    //     const { scrollTop, scrollLeft } = document.documentElement;
    //     Object.assign(ripple.style, {
    //         top: `${top + scrollTop}px`,
    //         left: `${left + scrollLeft}px`,
    //         width: width + "px",
    //         height: height + "px"
    //     });
    //     ripple.classList.add("ripple");
    //     document.body.appendChild(ripple);
    //     setTimeout(() => ripple.remove(), 800);
    // }

    // private _highlight(el: HTMLElement | null) {
    //     if (this._highlightElement) {
    //         const hel = this._highlightElement;
    //         hel.classList.add("out");
    //         setTimeout(() => hel.remove(), 500);
    //     }
    //
    //     if (el) {
    //         this._highlightElement = document.createElement("div");
    //         this._highlightElement.classList.add("highlight");
    //         document.body.appendChild(this._highlightElement);
    //
    //         const { left, top, width, height } = el.getBoundingClientRect();
    //         const { scrollTop, scrollLeft } = document.documentElement;
    //         Object.assign(this._highlightElement.style, {
    //             top: `${top + scrollTop}px`,
    //             left: `${left + scrollLeft}px`,
    //             width: width + "px",
    //             height: height + "px",
    //             opacity: 1
    //         });
    //     }
    // }

    // private _keydown({ code, ctrlKey, metaKey, altKey }: KeyboardEvent) {
    //     if (code === "Escape") {
    //         this.close();
    //     }
    //     if (!this._item) {
    //         return;
    //     }
    //
    //     const matchNumber = code.match(/Digit(\d)/);
    //     const index = (matchNumber && parseInt(matchNumber[1])) || NaN;
    //     if (!isNaN(index) && !!this._item.fields[index - 1]) {
    //         const input = this._getActiveInput();
    //         if ((ctrlKey || metaKey) && altKey && input) {
    //             this._fillIndex(index - 1);
    //         } else if (!input) {
    //             this._fieldIndex = index - 1;
    //         }
    //     }
    // }
    //
    // private _dragstart(index: number) {
    //     this._fieldIndex = index;
    //     document.body.classList.add("dragging");
    //     this.classList.add("dragging");
    // }

    // private _getFillableFromPoint(
    //     root: Document | ShadowRoot,
    //     x: number,
    //     y: number,
    //     depth = 0
    // ): HTMLInputElement | null {
    //     const els = root.elementsFromPoint(x, y);
    //
    //     // Check all elements on this level first
    //     const input = els.find(el => this._isElementFillable(el));
    //
    //     if (input) {
    //         return input as HTMLInputElement;
    //     }
    //
    //     // If no fillable elements on this level were found, go one level deeper
    //     for (const el of els) {
    //         if (el.shadowRoot && el.shadowRoot !== root) {
    //             const input = this._getFillableFromPoint(el.shadowRoot, x, y, depth + 1);
    //             if (input) {
    //                 return input;
    //             }
    //         }
    //     }
    //
    //     // If nothing was found, return null
    //     return null;
    // }

    // private _updateHovered = throttle((e: DragEvent) => {
    //     // console.log("update hovered", performance.now());
    //     const input = this._getFillableFromPoint(document, e.clientX, e.clientY);
    //     if (input !== this._hoveredInput) {
    //         this._highlight(input);
    //         this._hoveredInput = input;
    //     }
    // }, 50);
}

if (typeof window.extension === "undefined") {
    window.extension = new ExtensionContent();
    window.extension.init();
}
