import '@mescius/spread-sheets-formula-panel';
import '@mescius/spread-sheets-pivot-addon';
import '@mescius/spread-sheets-designer-resources-en';
import * as GC from "@mescius/spread-sheets-designer";
import '@mescius/spread-sheets-collaboration-addon';
import {Client, Connection} from "@mescius/js-collaboration-client";
import * as OT from "@mescius/js-collaboration-ot-client";
import {Presence} from "@mescius/js-collaboration-presence-client";
import {bind, bindPresence, IChangeSet, IPresence, type} from "@mescius/spread-sheets-collaboration-client";
import {SharedDoc} from "@mescius/js-collaboration-ot-client";

OT.TypesManager.register(type);

interface IDom extends HTMLElement {
    _mouseoverHandler: () => void;
    _mouseoutHandler: () => void;
}

const userCache = new Map<string, { doc: SharedDoc, designer: GC.Spread.Sheets.Designer.Designer, conn: Connection, userHostId: string }>();

export function createBindDesigner (hostId: string, userHostId: string, user: IPresence["user"]) {
    const designer = new GC.Spread.Sheets.Designer.Designer(hostId);
    const config = GC.Spread.Sheets.Designer.DefaultConfig;
    delete config.fileMenu;
    designer.setConfig(config);
    const workbook = designer.getWorkbook() as any;
    const conn = new Client().connect('room1');
    const doc = new OT.SharedDoc<any, IChangeSet>(conn);
    const presence = new Presence<IPresence>(conn);
    bind(workbook, doc);
    bindPresence(workbook, presence, user, {
        onPresencesUpdate: (presences) => {
            const presenceDiv = document.getElementById(userHostId);
            // Clear the current content
            cleatUserPresence(userHostId);

            // Iterate over presences and create a circle for each user
            presences.forEach(presence => {
                const user = presence.user;
                const circle = document.createElement('div') as unknown as IDom;
                circle.className = 'presence-item';
                circle.style.backgroundColor = user.color || '#007bff';
                circle.textContent = user.name.charAt(0).toUpperCase();

                // Define event handlers
                const mouseoverHandler = () => {
                    circle.style.width = '97px';
                    circle.style.padding = "0px 5px";
                    circle.textContent = user.name.charAt(0).toUpperCase() + user.name.slice(1);
                };

                const mouseoutHandler = () => {
                    circle.style.width = '24px';
                    circle.style.padding = "0px";
                    circle.textContent = user.name.charAt(0).toUpperCase();
                };

                // Store references to the handlers
                circle._mouseoverHandler = mouseoverHandler;
                circle._mouseoutHandler = mouseoutHandler;

                // Add event listeners
                circle.addEventListener('mouseover', mouseoverHandler);
                circle.addEventListener('mouseout', mouseoutHandler);

                presenceDiv.appendChild(circle);
            });
        }
    });
    userCache.set(user.id, { doc, designer, conn, userHostId });
}

export function removeBindDesigner (userId: string) {
    const instance = userCache.get(userId);
    if (instance) {
        const { doc, designer, conn, userHostId } = instance;
        conn.close();
        doc.destroy();
        designer.destroy();
        cleatUserPresence(userHostId);
    }
}

export function refreshDesigner () {
    userCache.forEach(value => {
        value.designer.refresh();
    })
}

function cleatUserPresence (userHostId: string) {
    const presenceDiv = document.getElementById(userHostId);
    // Clear the current content
    while (presenceDiv.firstChild) {
        const child = presenceDiv.firstChild as IDom;
        child.removeEventListener('mouseover', child._mouseoverHandler);
        child.removeEventListener('mouseout', child._mouseoutHandler);
        presenceDiv.removeChild(child);
    }
}

(window as any).userCache = userCache;
