// We need some kind of module resolver for @shared/db. We use module-alias.
require("module-alias/register");

import "./environment";
import * as path from "path";
import { client } from "./client";
import { createConnection, getConnectionOptions } from "typeorm";
import { assertOk } from "./util";
import { DB_ENTITIES } from "@shared/db/entities";
import { logger } from "./logging";
import { PluginManager } from "./plugin_manager";

export const plgMgr: PluginManager = new PluginManager(path.resolve(path.dirname(module.filename), "plugins"));
export const COMMAND_PREFIX = "/";

client.bot.on("ready", async () => {
    logger.info("Starting up NoctBot");
    await client.botUser.setActivity(`@${client.botUser.username} help`, { type: "PLAYING" });
    await assertOk(plgMgr.start(client.bot));
    logger.info("NoctBot is ready");
});

client.bot.on("message", async m => {
    if (m.author.id == client.botUser.id)
        return;

    if (m.channel.type != "text") {
        logger.warn("User %s (%s#%s) tried to execute command in DMs. Message: %s.", m.author.id, m.author.username, m.author.discriminator, m.content);
        await m.reply("DM commands are disabled, sorry!");
        return;
    }

    if (m.content.startsWith(COMMAND_PREFIX) && await plgMgr.runCommand("prefix", m, m.content.substring(COMMAND_PREFIX.length))) {
        return;
    }

    let content = m.cleanContent.trim();

    if (await plgMgr.trigger("message", m, content))
        return;

    if (m.mentions.users.size > 0 && m.mentions.users.has(client.botUser.id)) {
        const trimmedContent = m.content.trim();
        if (trimmedContent.startsWith(client.nameMention) || trimmedContent.startsWith(client.usernameMention)) {
            content = content.substring(`@${client.botUser.username}`.length).trim();
            const lowerCaseContent = content.toLowerCase();
            
            if (await plgMgr.runCommand("mention", m, content))
                return;

            if (await plgMgr.trigger("directMention", m, lowerCaseContent))
                return;
        }

        if (await plgMgr.trigger("indirectMention", m))
            return;
    }

    await plgMgr.trigger("postMessage", m);
});

async function main() {
    await createConnection({
        ...await getConnectionOptions(),
        entities: DB_ENTITIES
    });

    client.bot.login(process.env.BOT_TOKEN);
}

main();