import { isMainThread, parentPort, workerData } from 'worker_threads'
import { QuestionDb } from '../types/basicTypes'
import { SearchResultQuestion, countOfQdbs } from '../utils/qdbUtils'
import logger from '../utils/logger'
import { TaskObject } from './workerPool'
import { tesseractLoaded } from '../utils/tesseract'
import { handleSearch } from './handlers/handleSearch'
import { handleMerge } from './handlers/handleMerge'
import { handleDbEdit } from './handlers/handleDbEdit'
import { handleNewQuestions } from './handlers/handleNewQuestion'
import { handleNewDb } from './handlers/handleNewDb'
import { handleDbClean } from './handlers/handleDbClean'
import { handleQuestionsToPeers } from './handlers/handleQuestionsToPeers'
import { handleRmQuestions } from './handlers/handleRmQuestions'
import { handleUsersToPeers } from './handlers/handleUsersToPeers'
import { handleUserFilesToPeers } from './handlers/handleUserFilesToPeers'

export interface WorkerResult {
    msg: string
    workerIndex: number
    result?: SearchResultQuestion[] | number[][]
    error?: boolean
}

if (!isMainThread) {
    handleWorkerData()
}

async function handleWorkerData() {
    const {
        workerIndex,
        initData,
    }: { workerIndex: number; initData: Array<QuestionDb> } = workerData
    let qdbs: Array<QuestionDb> = initData
    const setQdbs = (newVal: Array<QuestionDb>) => {
        qdbs = newVal
    }

    const qdbCount = initData.length
    const { subjCount, questionCount } = countOfQdbs(initData)

    logger.Log(
        `[THREAD #${workerIndex}]: Worker ${workerIndex} reporting for duty! qdbs: ${qdbCount}, subjects: ${subjCount.toLocaleString()}, questions: ${questionCount.toLocaleString()}`
    )

    parentPort.on('message', async (msg: TaskObject) => {
        try {
            await tesseractLoaded

            await handleMessage(qdbs, msg, workerIndex, setQdbs)
        } catch (e) {
            console.error(e)
            parentPort.postMessage({
                msg: `From thread #${workerIndex}: unhandled error occured! (${
                    (msg as any)?.type
                })`,
                workerIndex: workerIndex,
                e: e,
            })
        }
    })
}

async function handleMessage(
    qdbs: QuestionDb[],
    msg: TaskObject,
    workerIndex: number,
    setQdbs: (newVal: QuestionDb[]) => void
) {
    if (msg.type === 'search') {
        await handleSearch(qdbs, msg, workerIndex)
    } else if (msg.type === 'merge') {
        await handleMerge(qdbs, msg, workerIndex)
    } else if (msg.type === 'dbEdit') {
        await handleDbEdit(qdbs, msg, workerIndex, setQdbs)
    } else if (msg.type === 'newQuestions') {
        await handleNewQuestions(qdbs, msg, workerIndex, setQdbs)
    } else if (msg.type === 'newdb') {
        await handleNewDb(qdbs, msg, workerIndex, setQdbs)
    } else if (msg.type === 'dbClean') {
        await handleDbClean(qdbs, msg, workerIndex)
    } else if (msg.type === 'rmQuestions') {
        await handleRmQuestions(qdbs, msg, workerIndex, setQdbs)
    } else if (msg.type === 'sendQuestionsToPeers') {
        await handleQuestionsToPeers(qdbs, msg, workerIndex)
    } else if (msg.type === 'sendUsersToPeers') {
        await handleUsersToPeers(qdbs, msg, workerIndex)
    } else if (msg.type === 'sendUserFilesToPeers') {
        await handleUserFilesToPeers(qdbs, msg, workerIndex)
    } else {
        logger.Log(`Invalid msg type!`, logger.GetColor('redbg'))
        console.error(msg)

        parentPort.postMessage({
            msg: `From thread #${workerIndex}: Invalid message type (${
                (msg as any)?.type
            })!`,
            workerIndex: workerIndex,
        })
    }
}
