"use strict";
/*
* Default web server that serves the API for the factory
* should be very simple to start with - direct trials and sources, no 'listing' - you gotta know what you're looking for.
* no user or session management either
*
* */
/*
* cluster web server that INGESTS new SUBMISSIONS into the database
* - inserts trials
* - inserts sources
* - inserts modlists
* - etc etc etc. Basically, the web server that takes in new data from the user and puts it into the database
*
* starting the injest server should also start database connections and ensure objects area valid
*
* */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.FactoryApiQueryServer = void 0;
const cors_1 = __importDefault(require("cors"));
const express_1 = __importStar(require("express"));
const cluster_1 = __importDefault(require("cluster"));
const FactoryDatabase_1 = require("../FactoryDatabase");
const Trial_1 = require("../Trial");
const Source_1 = require("../Source");
const ModList_1 = require("../ModList");
const Dataset_1 = require("../Dataset");
const FactoryApiIngest_1 = require("./FactoryApiIngest");
const path_1 = __importDefault(require("path"));
// STATIC CLASS - used to set up the web server and functionality to start/stop the cluster.
// script will use this to start the server
class FactoryApiQueryServer {
    //static app: Express;
    //static server: http.Server
    static startServer(port = 3009, instances = 8) {
        return __awaiter(this, void 0, void 0, function* () {
            if (cluster_1.default.isPrimary) {
                console.log(`Primary server starting on port ${port} with ${instances} instances`);
                for (let i = 0; i < instances; i++) {
                    cluster_1.default.fork();
                }
                cluster_1.default.on('exit', (worker) => {
                    console.log(`worker ${worker.process.pid} died`);
                });
            }
            else {
                yield FactoryDatabase_1.FactoryDatabase.initialize([
                    {
                        name: 'cache',
                        type: 'postgres',
                        host: process.env.PG_CACHE_HOST,
                        port: parseInt(process.env.PG_CACHE_PORT),
                        username: process.env.PG_CACHE_USER,
                        password: process.env.PG_CACHE_PASS,
                        poolSize: 4,
                        synchronize: true,
                        entities: [
                            Trial_1.Trial,
                            Source_1.Source,
                            ModList_1.ModList,
                            Dataset_1.GameFlowItemRecord,
                            Dataset_1.GameFlowElectricRecord,
                            Dataset_1.GameFlowCircuitRecord,
                            Dataset_1.GameFlowPollutionRecord,
                            Dataset_1.GameFlowSystemRecord,
                            FactoryApiIngest_1.FactoryApiExecutionRequest,
                            FactoryApiIngest_1.FactoryApiExecutionStatus
                        ]
                    }, /*{
                        name: 'storage',
                        type: 'postgres',
                        host: process.env.PG_STORAGE_HOST,
                        port: parseInt(process.env.PG_STORAGE_PORT),
                        username: process.env.PG_STORAGE_USER,
                        password: process.env.PG_STORAGE_PASS,
                        poolSize: 4,
                        synchronize: true,
                        entities: [
                            Trial,
                            Source,
                            ModList,
                            GameFlowItemRecord,
                            GameFlowElectricRecord,
                            GameFlowCircuitRecord,
                            GameFlowPollutionRecord,
                            GameFlowSystemRecord,
                            FactoryApiExecutionRequest,
                            FactoryApiExecutionStatus
                        ]
                    }*/
                ]);
                const ex = (0, express_1.default)();
                //trust proxy
                //ex.set('trust proxy', true)
                ex.use(express_1.default.json());
                ex.use((0, express_1.urlencoded)({ extended: true, limit: '100mb' }));
                const corsOptions = {
                    origin: ['https://api.factorioanalytics.com', 'https://www.factorioanalytics.com'],
                    optionsSuccessStatus: 200, // For legacy browser support
                    methods: "GET, POST", // allows different HTTP methods
                    mimeTypes: "application/json, application/javascript",
                };
                //ex.use(cors());
                // allow all mime types
                ex.use((0, cors_1.default)(corsOptions));
                ex.use(express_1.default.static(path_1.default.join(process.cwd(), 'public')));
                ex.get('/query/:id/:variant', (req, res) => {
                    try {
                        let id = req.params.id;
                        let variant = req.params.variant;
                        switch (variant) {
                            case 'source_raw':
                                FactoryDatabase_1.FactoryDatabase.FactoryDB.getRepository('Source').findOne({
                                    where: {
                                        id: id
                                    }
                                }).then((s) => {
                                    if (s)
                                        res.status(200).send(s.text);
                                    else
                                        res.status(404).send('Not found');
                                }).catch((e) => {
                                    res.status(500).send(e);
                                });
                                break;
                            case 'status':
                                FactoryDatabase_1.FactoryDatabase.findStatusAndTrialOfExecution(id).then((s) => {
                                    if (s)
                                        res.status(200).send(s);
                                    else
                                        res.status(404).send('Not found');
                                }).catch((e) => {
                                    res.status(500).send(e);
                                });
                                break;
                            case 'source':
                                // do source stuff. grab from DB and return it
                                FactoryDatabase_1.FactoryDatabase.FactoryDB.getRepository('Source').findOne({
                                    where: {
                                        id: id
                                    }
                                }).then((s) => {
                                    if (s)
                                        res.status(200).send(s);
                                    else
                                        res.status(404).send('Not found');
                                }).catch((e) => {
                                    res.status(500).send(e);
                                });
                                break;
                            case 'modlist':
                                // do modlist stuff
                                FactoryDatabase_1.FactoryDatabase.FactoryDB.getRepository('ModList').findOne({
                                    where: {
                                        id: id
                                    }
                                }).then((s) => {
                                    if (s)
                                        res.status(200).send(s);
                                    else
                                        res.status(404).send('Not found');
                                }).catch((e) => {
                                    res.status(500).send(e);
                                });
                                break;
                            case 'trial':
                                // do trial stuff
                                FactoryDatabase_1.FactoryDatabase.FactoryDB.getRepository('Trial').findOne({
                                    where: {
                                        id: id
                                    },
                                    relations: ['source']
                                }).then((s) => {
                                    if (s) {
                                        s.source = s.source.id;
                                        res.status(200).send(s);
                                    }
                                    else
                                        res.status(404).send('Not found');
                                }).catch((e) => {
                                    res.status(500).send(e);
                                });
                                break;
                            case 'data_item':
                                // do data_items stuff
                                FactoryDatabase_1.FactoryDatabase.loadDatasetRecords(id, 'item').then((s) => {
                                    if (s)
                                        res.status(200).send(s);
                                    else
                                        res.status(404).send('Not found');
                                }).catch((e) => {
                                    res.status(500).send(e);
                                });
                                break;
                            case 'data_electric':
                                // do data_electric stuff
                                FactoryDatabase_1.FactoryDatabase.loadDatasetRecords(id, 'electric').then((s) => {
                                    if (s)
                                        res.status(200).send(s);
                                    else
                                        res.status(404).send('Not found');
                                }).catch((e) => {
                                    res.status(500).send(e);
                                });
                                break;
                            case 'data_circuit':
                                // do data_circuit stuff
                                FactoryDatabase_1.FactoryDatabase.loadDatasetRecords(id, 'circuit').then((s) => {
                                    if (s)
                                        res.status(200).send(s);
                                    else
                                        res.status(404).send('Not found');
                                }).catch((e) => {
                                    res.status(500).send(e);
                                });
                                break;
                            case 'data_pollution':
                                // do data_pollution stuff
                                FactoryDatabase_1.FactoryDatabase.loadDatasetRecords(id, 'pollution').then((s) => {
                                    if (s)
                                        res.status(200).send(s);
                                    else
                                        res.status(404).send('Not found');
                                }).catch((e) => {
                                    res.status(500).send(e);
                                });
                                break;
                            case 'data_system':
                                // do data_system stuff
                                FactoryDatabase_1.FactoryDatabase.loadDatasetRecords(id, 'system').then((s) => {
                                    if (s)
                                        res.status(200).send(s);
                                    else
                                        res.status(404).send('Not found');
                                }).catch((e) => {
                                    res.status(500).send(e);
                                });
                                break;
                            case 'data_all':
                                // do data_all stuff
                                FactoryDatabase_1.FactoryDatabase.loadDatasetRecords(id, 'all').then((s) => {
                                    if (s)
                                        res.status(200).send(s);
                                    else
                                        res.status(404).send('Not found');
                                }).catch((e) => {
                                    res.status(500).send(e);
                                });
                                break;
                            default:
                                res.status(400).send('Invalid variant');
                                break;
                        }
                    }
                    catch (e) {
                        res.status(501).send(e);
                    }
                });
                ex.get('/check/:id', (req, res) => {
                    // checks if a source exists already or not
                    let id = req.params.id;
                    FactoryDatabase_1.FactoryDatabase.FactoryDB.getRepository('Source').exists({
                        where: {
                            id: id
                        }
                    }).then((s) => {
                        if (s != null)
                            res.status(200).send(s);
                        else
                            res.status(404).send('Not found');
                    }).catch((e) => {
                        res.status(500).send(e);
                    });
                });
                ex.get('/analysis/largestTrialForSource/:id', (req, res) => {
                    let id = req.params.id;
                    FactoryDatabase_1.FactoryDatabase.findLargestTrialOfSource(id).then((s) => {
                        if (s)
                            res.status(200).send(s);
                        else
                            res.status(404).send('Not found');
                    }).catch((e) => {
                        res.status(500).send(e);
                    });
                });
                ex.get('/analysis/defaultTrialForSource/:id', (req, res) => {
                    let id = req.params.id;
                    FactoryDatabase_1.FactoryDatabase.checkIfDefaultTrialExists(id).then((s) => {
                        if (s)
                            res.status(200).send(s);
                        else
                            res.status(404).send('Not found');
                    }).catch((e) => {
                        res.status(500).send(e);
                    });
                });
                // need a path for...
                /*
                * 1. Check if a Source has been submitted and saved yet
                * 2. Retrieve the most complete dataset for a Source (add to normal query functionality)
                * 3. Retrieve a summary of the largest dataset for a Source
                * */
                ex.listen(port, () => {
                    console.log(`Server instance started on port ${port}`);
                });
            }
        });
    }
}
exports.FactoryApiQueryServer = FactoryApiQueryServer;
//# sourceMappingURL=FactoryApiQuery.js.map