import {Client, Connection} from "@mescius/js-collaboration-client";
import * as OT from "@mescius/js-collaboration-ot-client";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import richText from 'rich-text';
import Quill from 'quill';
import 'quill/dist/quill.snow.css';
import {SharedDoc} from "@mescius/js-collaboration-ot-client";
import {Presence} from "@mescius/js-collaboration-presence-client";
import {bindPresence, clearUserPresence, IPresence, IUser} from "./presence";
import {destroyQuill} from "./util";

export const type = richText.type;
OT.TypesManager.register(type);

const userCache = new Map<string, { doc: SharedDoc, quill: Quill, conn: Connection, userHostId: string, hostId: string }>();
let isCreated = false;
export async function createBindQuill (hostId: string, userHostId: string, user: IUser) {
    const quill = new Quill(`#${hostId}`, { theme: 'snow' });
    const conn = new Client().connect('room1');
    const doc = new OT.SharedDoc(conn);
    const presence = new Presence<IPresence>(conn);
    userCache.set(user.id, { doc, quill, conn, userHostId, hostId });
    await doc.fetch();
    if (!doc.type && isCreated === false) {
        isCreated = true;
        await doc.create('', richText.type.uri, {});
        bindQuillAndPresence(quill, doc, presence, user, userHostId);
    } else {
        bindQuillAndPresence(quill, doc, presence, user, userHostId);
    }
}

export function removeBindQuill (userId: string) {
    const instance = userCache.get(userId);
    if (instance) {
        const { doc, quill, conn, userHostId, hostId } = instance;
        conn.close();
        doc.destroy();
        destroyQuill(quill, document.getElementById(hostId));
        clearUserPresence(userHostId);
    }
}

function bindQuillAndPresence (quill: Quill, doc: OT.SharedDoc, presence: Presence<IPresence>, user: any, userHostId: string) {
    bind(quill, doc);
    bindPresence(presence, user, userHostId);
}

async function bind(quill: Quill, doc: OT.SharedDoc) {
    await doc.subscribe();
    quill.setContents(doc.data as any);
    quill.on('text-change', function (delta: unknown, _oldDelta: unknown, source: string) {
        console.log('text-change');
        if (source !== 'user') return;
        doc.submitOp(delta, { source: doc.connection.id });
    });
    doc.on('op', function (op, source) {
        if (source === doc.connection.id) return;
        quill.updateContents(op as any);
    });

    doc.on('error', (err) => console.error(err))
}
