
import { Doc } from "../../../../../fields/Doc";
import { Docs } from "../../../../documents/Documents";
import { Col } from "./DocCreatorMenu";
import { DynamicField } from "./FieldTypes/DynamicField";
import { Field, FieldSettings, ViewType } from "./FieldTypes/Field";
import {  } from "./FieldTypes/FieldUtils";
import { } from "./FieldTypes/StaticField";

export class Template {

    mainField: DynamicField;

    constructor(templateInfo: FieldSettings) {
        this.mainField = this.setupMainField(templateInfo);
    }

    get childFields(): Field[] { return this.mainField.getSubfields };
    get allFields(): Field[] { return this.mainField.getAllSubfields };
    get contentFields(): Field[] { return this.allFields.filter(field => field.getViewType === ViewType.STATIC) };

    getFieldByID = (id: number): Field => {
        return this.allFields.filter(field => field.getID === id)[0];
    }

    setupMainField = (templateInfo: FieldSettings) => {
        return new DynamicField(templateInfo, ViewType.FREEFORM, 0);
    }

    isValidTemplate = (cols: Col[]) => {
        return this.maxMatches(this.getMatches(cols)) === this.contentFields.length;
    }

    getMatches = (cols: Col[]) => {
        const matches: number[][] = Array(this.contentFields.length)
            .fill([])
            .map(() => []);

        this.contentFields.forEach((field, i) => {
            matches[i].concat(field.matches(cols));
        });

        return matches;
    }

    maxMatches = (matches: number[][]) => {
        const fieldsCt = this.contentFields.length;
        const used: boolean[] = Array(fieldsCt).fill(false);
        const mt: number[] = Array(fieldsCt).fill(-1);

        const augmentingPath = (v: number): boolean => {
            if (used[v]) return false;
            used[v] = true;
            for (const to of matches[v]) {
                if (mt[to] === -1 || augmentingPath(mt[to])) {
                    mt[to] = v;
                    return true;
                }
            }
            return false;
        };

        for (let v = 0; v < fieldsCt; ++v) {
            used.fill(false);
            augmentingPath(v);
        }

        let count: number = 0;

        for (let i = 0; i < fieldsCt; ++i) {
            if (mt[i] !== -1) ++count;
        }

        return count;
    };

}