export function getMetaContent(name: string): string | null {
    const meta = document.querySelector('meta[name="' + (name as any) + '"]');
    if (meta) {
        return meta.getAttribute('content');
    }
    return null;
}

export function getDocWidth(): number {
    return document.documentElement.clientWidth;
}

export function getDocHeight(): number {
    return document.documentElement.clientHeight;
}

export function maxZIndex(elements?: HTMLCollectionOf<Element> | NodeListOf<Element>): number {
    if (!elements) {
        elements = document.body.getElementsByTagName('*');
    }
    let result = -1;
    for (let i = 0; i < elements.length; i++) {
        const style = window.getComputedStyle(elements[i]);
        const zIndex = Number(style.zIndex);
        if (result < zIndex) {
            result = zIndex;
        }
    }
    return result;
}

export function minTopZIndex(step: number = 1): number {
    const maxValue = 2147483584;
    const elements = document.body.querySelectorAll('*');
    const zIndex = maxZIndex(elements);
    if (zIndex > maxValue - step) {
        return maxValue;
    } else {
        return zIndex + step;
    }
}

export function selectRange(element: HTMLElement, start: number, length: number): number {
    let end = start + length;
    if (element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement) {
        element.setSelectionRange(start, end);
    }
    element.focus();
    return end;
}

export function scrollToTop(): void {
    window.document.body.scrollIntoView();
}

export function scrollToBottom(): void {
    let top = window.document.body.scrollHeight;
    window.scroll({top: top, left: 0, behavior: 'smooth'});
}

export function matchesKeyEvent(event: KeyboardEvent, options: Record<string, any>): boolean {
    if (options) {
        if (options.ctrlKey === true && event.ctrlKey !== true) {
            return false;
        }
        if (options.altKey === true && event.altKey !== true) {
            return false;
        }
        if (options.shiftKey === true && event.shiftKey !== true) {
            return false;
        }
        if (options.key) {
            return options.key.toLowerCase() === event.key.toLowerCase();
        }
        if (options.code) {
            return options.code.toLowerCase() === event.code.toLowerCase();
        }
    }
    return false;
}

export function replaceKeyEvent(element: HTMLElement, handler: () => void, options: Record<string, any>): void {
    element.onkeydown = (event: KeyboardEvent) => {
        if (matchesKeyEvent(event, options)) {
            event.preventDefault();
        }
    };
    element.onkeyup = (event: KeyboardEvent) => {
        if (matchesKeyEvent(event, options)) {
            event.preventDefault();
            handler();
        }
    };
}

export function observeHeightChange(element: Element, onChange: (newHeight: string, oldHeight: string) => void): MutationObserver {
    let oldHeight = window.getComputedStyle(element).getPropertyValue('height');
    const MutationObserver = window.MutationObserver || (window as any)['webkitMutationObserver'] || (window as any)['MozMutationObserver'];
    let observer = new MutationObserver(() => {
        let height = window.getComputedStyle(element).getPropertyValue('height');
        if (height !== oldHeight) {
            onChange(height, oldHeight);
        }
    });
    observer.observe(element, {
        childList: true,
        attributes: true,
        characterData: true,
        subtree: true,
    });
    return observer;
}

export function getTopVerticallyCenteredOnPage(element: HTMLElement): number {
    const height = element.offsetHeight;
    const docHeight = getDocHeight();
    const heightRatio = height / docHeight;
    const baseline = 33 + (50 - 33) * heightRatio;
    const baseTop = docHeight * baseline / 100;
    let top = baseTop - height / 2;
    top = Math.max(top, 8);
    return top;
}
