module main;

import std.stdio: writeln;
import asdf: deserialize, serializeToJson;

import util;
import listener;

import database.sqlite.db;
__gshared SQLite3DB db;

int main(string[] args) {
	import core.stdc.stdio;

	char buf;
	char[] fileStr;
	auto file = fopen("config.json", "r");
	if (file is null) return 1;
	while ((buf = cast(char)fgetc(file)) != 255)
		fileStr ~= buf;
	fclose(file);

	cfg = fileStr.deserialize!Config;
	cfg.token = "Authorization: Bearer " ~ cfg.token;

	if (args.length == 5 && args[1] == "get-token") {
		auto rq = mkrqst(
			args[2]~"/_matrix/client/v3/login", "POST",
			`{
				"identifier": {
					"type": "m.id.user",
					"user": "`~args[3]~`"
				},
				"initial_device_display_name": "Neptune Bot",
				"password": "`~args[4]~`",
				"type": "m.login.password"
			}`,
			true
		);

		if (rq.status != 200) {
			writeln("Something went wrong :(\n", rq.body);
			return 1;
		}

		struct Login {
			string access_token;
		}

		writeln("Your access token: \033[0;32m", (rq.body.deserialize!Login).access_token, "\033[0m.\n",
				"Save it!");
		return 0;
	}

	init;

	import core.thread;
	import commands.slaves;
	alias sl = commands.slaves;
	static foreach (member; __traits(allMembers, sl)) {
		static foreach (attr; __traits(getAttributes, __traits(getMember, sl, member))) {
			static if (is(attr == Parallel)) {
				new Thread(&__traits(getMember, sl, member)).start;
			}
		}
	}

	import commands.apod,
		commands.misc,
		commands.mozhi,
		commands.moderation;

	listen!(
		commands.apod,
		commands.misc,
		commands.mozhi,
		commands.moderation,
	);

	return 0;
}

// https://m.lost-skunk.cc/_matrix/client/v3/presence/@me:lost-skunk.cc/status
void init() {
	db = SQLite3DB(cfg.database_path);
	syncUrl = "/_matrix/client/v3/sync?set_presence=online";
	db.exec("create table if not exists client (latest_batch string)");
	db.exec("create table if not exists room_pls (room string, user string, pl integer)");
	auto q = db.query("select latest_batch from client");

	if (q.step) initialBatch = q.get!string;
	else {
		import api_data: Sync;
		writeln("starting initial sync..");
		Sync snk = mkhsrq(syncUrl).body.deserialize!Sync;
		initialBatch = snk.next_batch;
		db.exec("insert into client (latest_batch) values (?)", initialBatch);
		writeln("done!");

		foreach(room; snk.rooms.join.keys) fetchMembers(room);
	}

	syncUrl ~= "&since=";
}