import { ITrackable } from '@iqser/common-ui';
import type { List } from '@iqser/common-ui/lib/utils';
import type { AnnotationWrapper } from '@models/file/annotation.wrapper';
import { Dayjs } from 'dayjs';

export function hexToRgb(hex: string) {
    const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
    return result
        ? {
              r: parseInt(result[1], 16),
              g: parseInt(result[2], 16),
              b: parseInt(result[3], 16),
          }
        : null;
}

export function hexToRgba(hex: string, alpha: number) {
    const rgb = hexToRgb(hex);
    return rgb ? `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, ${alpha})` : null;
}

export function getFirstRelevantTextPart(text: string, direction: 'FORWARD' | 'BACKWARD') {
    let spaceCount = 0;
    let accumulator = '';
    const breakChars = [':', ' '];

    const handle = (i: number) => {
        const char = text[i];
        if (breakChars.indexOf(char) >= 0) {
            spaceCount += 1;
        }

        accumulator += char;

        return spaceCount >= 3;
    };

    if (direction === 'FORWARD') {
        for (let i = 0; i < text.length; i++) {
            const shouldBreak = handle(i);
            if (shouldBreak) {
                break;
            }
        }
    } else {
        for (let i = text.length - 1; i >= 0; i--) {
            const shouldBreak = handle(i);
            if (shouldBreak) {
                break;
            }
        }
    }
    if (direction === 'BACKWARD') {
        accumulator = accumulator.split('').reverse().join('');
    }
    return accumulator;
}

export function lastIndexOfEnd(str: string, search: string) {
    const io = str.lastIndexOf(search);
    return io === -1 ? -1 : io + search.length;
}

export function toNumber(str: string) {
    try {
        return parseInt(`${str}`.replace(/\D/g, ''), 10);
    } catch (e) {
        return 0;
    }
}

export function removeBraces(str: string): string {
    return str.replace(/[{}]/g, '');
}

export function toSnakeCase(str: string): string {
    return str
        .replace(/([a-z])([A-Z])/g, '$1-$2')
        .replace(/[\s_]+/g, '_')
        .toLowerCase();
}

export function compareLists(l1: string[], l2: string[]) {
    if (l1.length !== l2.length) {
        return true;
    }

    for (let idx = 0; idx < l1.length; ++idx) {
        if (l1[idx] !== l2[idx]) {
            return true;
        }
    }

    return false;
}

export const byPage = (page: number) => (annotation: AnnotationWrapper) => annotation.pageNumber === page;

export function byId<T extends ITrackable>(id: string) {
    return (item: T) => item.id === id;
}

export function getLast<T>(list: List<T>) {
    return list[list.length - 1];
}

export const dateWithoutTime = (date: Dayjs) => date.set('h', 0).set('m', 0).set('s', 0).set('ms', 0);

export function hasChanges<T>(left: T, right: T) {
    return JSON.stringify(left) !== JSON.stringify(right);
}

export function moveElementInArray<T>(array: T[], element: T, index: number) {
    const result = array.filter(e => e !== element);
    result.splice(index, 0, element);
    return result;
}

export function calcTextWidthInPixels(text: string): number {
    const temporaryElement = document.createElement('span');
    document.body.appendChild(temporaryElement);

    temporaryElement.style.font = 'times new roman';
    temporaryElement.style.fontSize = 13 + 'px';
    temporaryElement.style.height = 'auto';
    temporaryElement.style.width = 'auto';
    temporaryElement.style.position = 'absolute';
    temporaryElement.style.whiteSpace = 'no-wrap';
    temporaryElement.innerHTML = text;

    const width = Math.ceil(temporaryElement.clientWidth);
    document.body.removeChild(temporaryElement);

    return width;
}
