"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getEventShemas = void 0;
const path = require("path");
const fs = require("fs");
const glob = require("glob");
const client_types_1 = require("@syftdata/common/lib/client_types");
const utils_1 = require("@syftdata/common/lib/utils");
function getEventSchemasFromFolder(folder) {
    const files = glob.sync(folder + '/**/*', {
        nodir: true
    });
    (0, utils_1.logVerbose)('Searching for spec files under ' + folder);
    const models = new Map();
    const modelFields = new Map();
    const getOrAddModel = (name, exported) => {
        if (models.has(name)) {
            return models.get(name);
        }
        const model = {
            name,
            zodType: 'z.object({})',
            fields: [],
            traits: [],
            eventType: client_types_1.SyftEventType.TRACK,
            documentation: `This model generates the "${name
                .replace(/([A-Z])/g, ' $1')
                .trim()}" event.`,
            exported
        };
        models.set(name, model);
        modelFields.set(name, new Set());
        return model;
    };
    const addFieldIfPossible = (modelName, field) => {
        const model = getOrAddModel(modelName, false);
        const existingFields = modelFields.get(modelName);
        const fieldNameComps = field.name.split('?');
        if (existingFields?.has(fieldNameComps[0]) === true) {
            return;
        }
        existingFields?.add(fieldNameComps[0]);
        if (fieldNameComps.length > 1) {
            field.name = fieldNameComps[0];
            field.isOptional = true;
        }
        model.fields.push(field);
    };
    const schemas = files.map((file) => {
        const name = path.basename(file);
        (0, utils_1.logVerbose)('Reading schema file: ' + file);
        const capitalName = (0, utils_1.capitalize)(name);
        const model = getOrAddModel(capitalName, true);
        let eventType = client_types_1.SyftEventType.TRACK;
        const contents = fs.readFileSync(file, 'utf8');
        const fieldLines = contents
            .split('\n')
            .map((line) => line.trim().split('\t'));
        const specTypeLines = fieldLines.filter((line) => line[0].startsWith('spec_'));
        const subModelLines = fieldLines.filter((line) => line[0].includes('.'));
        const validFieldLines = fieldLines.filter((line) => line[0] !== '' && !line[0].startsWith('spec_') && !line[0].includes('.'));
        validFieldLines.forEach((line) => {
            let [name, type, documentation] = line;
            if (type === 'String' || type === 'Number' || type === 'Boolean') {
                type = type.toLocaleLowerCase();
            }
            addFieldIfPossible(capitalName, {
                name,
                type: {
                    name: type,
                    zodType: 'z.string()'
                },
                isOptional: false,
                documentation
            });
        });
        subModelLines.forEach((line) => {
            let [fullname, type, documentation] = line;
            const isArray = fullname.includes('.$.');
            let [_subModelName, name] = fullname.split('.');
            if (isArray) {
                [_subModelName, name] = fullname.split('.$.');
            }
            const subModelName = (0, utils_1.capitalize)(_subModelName);
            if (type === 'String' || type === 'Number' || type === 'Boolean') {
                type = type.toLocaleLowerCase();
            }
            addFieldIfPossible(subModelName, {
                name,
                type: {
                    name: type,
                    zodType: 'z.string()'
                },
                isOptional: false,
                documentation
            });
            if (isArray) {
                addFieldIfPossible(capitalName, {
                    name: _subModelName,
                    type: {
                        name: `${subModelName}[]`,
                        zodType: 'z.array()'
                    },
                    isOptional: false,
                    documentation
                });
            }
            else {
                addFieldIfPossible(capitalName, {
                    name: _subModelName,
                    type: {
                        name: `${subModelName}`,
                        zodType: 'z.object()'
                    },
                    isOptional: false,
                    documentation
                });
            }
        });
        if (specTypeLines.length > 0) {
            specTypeLines.forEach((specTypeData) => {
                if (specTypeData[0] === 'spec_type') {
                    if (specTypeData.length > 1) {
                        const eventTypeStr = specTypeData[1].toLocaleUpperCase();
                        eventType = client_types_1.SyftEventType[eventTypeStr];
                    }
                }
                else if (specTypeData[0] === 'spec_description') {
                    if (specTypeData.length > 1) {
                        model.documentation = specTypeData[1];
                    }
                }
            });
        }
        model.eventType = eventType;
        return model;
    });
    return [...models.values(), ...schemas];
}
function getEventShemas(platform, product) {
    let eventSchemas = getEventSchemasFromFolder(path.join(__dirname, '../../assets/models', platform));
    eventSchemas = eventSchemas.concat(getEventSchemasFromFolder(path.join(__dirname, '../../assets/models/common')));
    if (product != null) {
        eventSchemas = eventSchemas.concat(getEventSchemasFromFolder(path.join(__dirname, '../../assets/models', product)));
    }
    const schemaNames = new Set();
    eventSchemas = eventSchemas.filter((schema) => {
        if (schemaNames.has(schema.name)) {
            return false;
        }
        schemaNames.add(schema.name);
        return true;
    });
    return {
        config: {
            version: '0.0.1',
            projectName: 'test'
        },
        eventSchemas
    };
}
exports.getEventShemas = getEventShemas;
