import { vertexsMap, LogicItem, ProcessComponent } from '.';
import { logicItemKeyOfLogicItem, logicItemArrayKeyOfLogicItem, LogicNode } from './logic/LogicItem';

export interface TypeCheckNote {
    status: string,
    type: string,
    message?: string[],
}

export interface TypeCheckAttribute {
    id: string,
    parentAttr?: string,
    typeCheckNote?: TypeCheckNote,
}
export interface TypeCheckRecord {
    id: string,
    logicId?: string,
    typeCheckNote: TypeCheckNote,
    processComponentId?: string,
    attributes?: TypeCheckAttribute[],
}

export default {
    records: [] as Array<TypeCheckRecord>,
    push(record: TypeCheckRecord) {
        const pos = this.deleteOwn(record.id);

        if(record.typeCheckNote?.message?.filter)
            record.typeCheckNote.message = record.typeCheckNote.message.filter((item) => !!item);

        if(!record.typeCheckNote || record.typeCheckNote.status === 'success'
            || (record.typeCheckNote && record.typeCheckNote.message && record.typeCheckNote.message.length === 0))
            return;

        if(pos === -1)
            this.records.unshift(record);
        else
            this.records.splice(pos, 0, record);
    },
    deleteOwn(id: string) {
        const pos = this.records.findIndex((item) => item.id === id);
        if(pos >= 0)
            this.records.splice(pos, 1);
        return pos;
    },
    delete(id: string) {
        const node = vertexsMap.get(id);
        this.deleteOwn(id);

        if(node) {
            let children: LogicItem[] = [];
            [...logicItemKeyOfLogicItem, ...logicItemArrayKeyOfLogicItem].forEach((key) => {
                const item = (node as LogicItem)[key as keyof LogicItem];
                if(item)
                    children = children.concat(item);
            });

            children.forEach((item) => {
                this.delete(item.id);
            });
        }
    },
    deleteByProcess(processId: string) {
        this.records = this.records.filter((record) => {
            const { processComponentId } = record;
            if (processComponentId && (vertexsMap.get(processComponentId) as ProcessComponent)?.process.id === processId) {
                return false;
            }
            return true;
        });
    },
    clear() {
        this.records = [];
    },
    pushAll(records: TypeCheckRecord[], outerId?: { processComponentId: string, logicId: string }) {
        if (!Array.isArray(records))
            return;

        for (const record of records) {
            const { id, logicId = outerId?.logicId, typeCheckNote, processComponentId = outerId?.processComponentId, attributes } = record;

            this.push({
                id,
                logicId,
                typeCheckNote,
                processComponentId,
                attributes,
            });

            ['body', 'consequent', 'alternate'].forEach((key) => {
                if (!(record as any)[key])
                    return;

                this.pushAll((record as any)[key], { processComponentId, logicId });
            });

            if ((record as any)['cases']) {
                for (const rec of (record as any)['cases']) {
                    this.pushAll(rec.consequent, { processComponentId, logicId });
                }
            }

            if ((record as any)['right'] &&
                (record as any)['right'].level === 'logicNode') {
                this.pushAll([(record as any)['right']], { processComponentId, logicId });
            }
        }
    },
};