import messageSound from '../assets/message.mp3';

export interface ISwipe {
    content: string;
    summary?: string;
    cost: number;
}

export interface IMessage {
    role: 'user' | 'assistant' | 'system';
    currentSwipe: number;
    swipes: ISwipe[];
    technical?: boolean;
}

export namespace MessageTools {
    export const getSwipe = (message?: IMessage | null) => message?.swipes[message?.currentSwipe];
    export const create = (content: string, role: IMessage['role'] = 'user', technical = false, cost = 0): IMessage => (
        { role, currentSwipe: 0, swipes: [{ content, cost }], technical }
    );

    export const playReady = () => {
        messageSound.currentTime = 0;
        messageSound.play();
    }

    export const format = (message: string): string => {
        const replaceRegex = /(\*\*?|")/ig;
        const splitToken = '___SPLIT_AWOORWA___';

        const preparedMessage = message.replace(replaceRegex, `${splitToken}$1${splitToken}`);
        const parts = preparedMessage.split(splitToken);

        const stack: string[] = [];

        let resultHTML = '';

        for (const part of parts) {
            const isClose = stack.at(-1) === part;
            if (isClose) {
                stack.pop();
                if (part === '*' || part === '**') {
                    resultHTML += `</span>`;
                } else if (part === '"') {
                    resultHTML += `"</span>`;
                }
            } else {
                if (part === '*') {
                    stack.push(part);
                    resultHTML += `<span class="italic">`;
                } else if (part === '**') {
                    stack.push(part);
                    resultHTML += `<span class="bold">`;
                } else if (part === '"') {
                    stack.push(part);
                    resultHTML += `<span class="quote">"`;
                } else {
                    resultHTML += part;
                }
            }
        }

        while (stack.length) {
            const part = stack.pop();
            if (part === '*' || part === '**') {
                resultHTML += `</span>`;
            } else if (part === '"') {
                resultHTML += `"</span>`;
            }
        }

        return resultHTML;
    }

    export const trimSentence = (text: string): string => {
        let latestEnd = -1;
        let latestPairEnd = text.length;
        for (const end of '.!?;…*"`)}]\n') {
            latestEnd = Math.max(latestEnd, text.lastIndexOf(end));
        }

        for (const char of '*"`') {
            const idx = text.lastIndexOf(char);

            const match = text.match(new RegExp(`[${char}]`, 'g'));
            if (match && match.length % 2 !== 0) {
                latestPairEnd = Math.min(latestPairEnd, idx - 1);
            }
        }

        latestEnd = Math.min(latestEnd, latestPairEnd);

        if (latestEnd > 0) {
            text = text.slice(0, latestEnd + 1);
        }
        return text.trim();
    }

    export const updateSwipe = (messages: IMessage[], index: number, update: Partial<ISwipe>, cost = 0) => (
        messages.map(
            (m, i) => ({
                ...m,
                swipes: i === index
                    ? m.swipes.map((s, si) => (si === m.currentSwipe ? { ...s, ...update, cost: (s.cost || 0) + cost } : s))
                    : m.swipes
            })
        )
    )
}