import SequelizeAutoService from "./core/services/sequelize-auto";
import utils from "./utils/general-utils";
import { TableProperty } from "./core/classes/TableProperty";
import { Table } from "./core/classes/Table";
import { IConfig } from "./interfaces/config";

import * as modelWriter from "./core/write-scripts/write-dao";
import * as ormWrapperWriter from "./core/write-scripts/write-orm-wrapper";
import * as interfaceWriter from "./core/write-scripts/write-interfaces";
import * as controllerWriter from "./core/write-scripts/express/write-controller";
import * as serviceWriter from "./core/write-scripts/write-service";
import * as routesWriter from "./core/write-scripts/express/write-route";
import * as datasourceWriter from "./core/write-scripts/write-datasource";
import * as serverFileWriter from "./core/write-scripts/express/write-server";
import * as packageJSONWriter from "./core/write-scripts/write-package-json";
import * as envWriter from "./core/write-scripts/write-env";
import * as gitIgnoreWriter from "./core/write-scripts/write-gitignore";
import * as respondFnWriter from "./core/write-scripts/express/write-respond-fn";
import * as tsConfigWriter from "./core/write-scripts/write-ts-config";

export const bootstrap = async (config: IConfig) => {
    const tables = await SequelizeAutoService.getTables(config);
    const tablesToWrite: Table[] = [];

    for (let x in tables) { 
        let tableName: string = x;

        if (tables.hasOwnProperty(tableName) && utils.isTableAllowed(tableName, config.ORM_GENERATE.skipTables)) { 
            let table = new Table({
                tableName: x,
                metadata: {
                    lookupTableName: config.ORM_GENERATE.lookup && config.ORM_GENERATE.lookup.tableName
                }
            });
            for (let y in tables[x]) { 
                if (tables[x].hasOwnProperty(y)) {
                    let tablePropsObj = tables[x];       
                    table.properties.push(new TableProperty(y, table.tableName, tablePropsObj, config));
                }
            }

            tablesToWrite.push(table);
        }
    }

    // WRITE MODEL
    modelWriter.generate(tablesToWrite, config);

    // WRITE DATASOURCE
    datasourceWriter.generate(config);

    // WRITE ORM WRAPPER
    ormWrapperWriter.generate(config);

    // WRITE INTERFACE FILE
    interfaceWriter.generate(tablesToWrite, config);


    // -------------------------------------------------------//

    if (config.ORM_GENERATE.shouldGenerateServices) {
        // WRITE SERVICES
        serviceWriter.generate(tablesToWrite, config);
    }
    
    if (config.CRUD_GENERATE.shouldGenerate) {
        // WRITE CONTROLLERS
        controllerWriter.generate(tablesToWrite, config);

        // WRITE ROUTES
        routesWriter.generate(tablesToWrite, config);

        // WRITE server.js, .env, package.json, .gitignore
        serverFileWriter.generate(tablesToWrite, config);
        packageJSONWriter.generate();
        envWriter.generate(config);
        gitIgnoreWriter.generate();
        respondFnWriter.generate();
        tsConfigWriter.generate();
    }
}

