#include <sqlite3.h>
#include <time.h>
#include <string.h>
#include "bbs.h"

extern struct bbs_config conf;
extern struct user_record *gUser;

struct ptr_vector blog_load(void) {
	static char buffer[PATH_MAX];

	struct ptr_vector entries = EMPTY_PTR_VECTOR;
	const char *sql = "SELECT author, title, body, date FROM blog ORDER BY date DESC";
	int rc;
	sqlite3 *db;
	sqlite3_stmt *res;

	snprintf(buffer, PATH_MAX, "%s/blog.sq3", conf.bbs_path);

	rc = sqlite3_open(buffer, &db);

	if (rc != SQLITE_OK) {
		dolog("Cannot open database: %s", sqlite3_errmsg(db));
		return EMPTY_PTR_VECTOR;
	}
	sqlite3_busy_timeout(db, 5000);
	rc = sqlite3_prepare_v2(db, sql, -1, &res, 0);

	if (rc != SQLITE_OK) {
		dolog("Failed to execute statement: %s", sqlite3_errmsg(db));
		sqlite3_close(db);
		return EMPTY_PTR_VECTOR;
	}
	init_ptr_vector(&entries);
	while (sqlite3_step(res) == SQLITE_ROW) {
		struct blog_entry_t *entry = (struct blog_entry_t *)malloz(sizeof(struct blog_entry_t));
		entry->author = strdup(sqlite3_column_text(res, 0));
		entry->subject = strdup(sqlite3_column_text(res, 1));
		entry->body = strdup(sqlite3_column_text(res, 2));
		entry->date = sqlite3_column_int(res, 3);
		ptr_vector_append(&entries, entry);
	}

	sqlite3_finalize(res);
	sqlite3_close(db);

	return entries;
}

void blog_display() {
	struct ptr_vector entries = blog_load();
	struct tm thetime;
	static const char *const days[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "???"};
	static const char *const months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "???"};
	char c;
	int hour;
	int j;
	int lines = 2;
	s_printf("\e[2J\e[1;1H");
	s_printf(get_string(280));
	s_printf(get_string(281));

	if (ptr_vector_len(&entries) == 0) {
		s_printf(get_string(282));
		s_printf(get_string(6));
		s_getchar();
		return;
	}

	c = 'y';

	for (size_t i = 0; i < ptr_vector_len(&entries); i++) {
		struct blog_entry_t *entry = ptr_vector_get(&entries, i);
		localtime_r(&entry->date, &thetime);

		s_printf(get_string(283), entry->subject, entry->author);
		lines++;
		if (lines == 22 && tolower(c) != 'c') {
			s_printf("\r\n");
			s_printf(get_string(223));
			c = s_getchar();
			if (tolower(c) == 'n') {
				break;
			}
			s_printf("\r\n\r\n");
			lines = 0;
		}
		if (thetime.tm_hour >= 12) {
			hour = thetime.tm_hour - 12;
		} else {
			hour = thetime.tm_hour;
		}
		s_printf(get_string(284), (hour == 0 ? 12 : hour), thetime.tm_min, (thetime.tm_hour >= 12 ? "pm" : "am"), days[thetime.tm_wday], months[thetime.tm_mon], thetime.tm_mday, thetime.tm_year + 1900);

		lines++;
		if (lines == 22 && tolower(c) != 'c') {
			s_printf("\r\n");
			s_printf(get_string(223));
			c = s_getchar();
			if (tolower(c) == 'n') {
				break;
			}
			s_printf("\r\n\r\n");
			lines = 0;
		}

		s_printf("\r\n\e[0m");
		lines++;
		if (lines == 22 && tolower(c) != 'c') {
			s_printf("\r\n");
			s_printf(get_string(223));
			c = s_getchar();
			if (tolower(c) == 'n') {
				break;
			}
			s_printf("\r\n\r\n");
			lines = 0;
		}
		for (j = 0; j < strlen(entry->body); j++) {
			if (entry->body[j] == '\r') {
				s_printf("\r\n");
				lines++;
				if (lines == 22 && tolower(c) != 'c') {
					s_printf("\r\n");
					s_printf(get_string(223));
					c = s_getchar();
					if (tolower(c) == 'n') {
						break;
					}
					s_printf("\r\n\r\n");
					lines = 0;
				}
			} else {
				s_printf("%c", entry->body[j]);
			}
		}

		if (tolower(c) == 'n') {
			break;
		}
		s_printf("\r\n");
		lines++;
		if (lines == 22 && tolower(c) != 'c') {
			s_printf("\r\n");
			s_printf(get_string(223));
			c = s_getchar();
			if (tolower(c) == 'n') {
				break;
			}
			s_printf("\r\n\r\n");
			lines = 0;
		}
	}
	ptr_vector_apply(&entries, free);
	destroy_ptr_vector(&entries);

	s_printf(get_string(6));
	s_getchar();
}

void blog_write() {
	char *csql = "CREATE TABLE IF NOT EXISTS blog ("
	             "id INTEGER PRIMARY KEY,"
	             "author TEXT COLLATE NOCASE,"
	             "title TEXT,"
	             "body TEXT,"
	             "date INTEGER);";

	char *isql = "INSERT INTO blog (author, title, body, date) VALUES(?, ?, ?, ?)";
	int rc;
	sqlite3 *db;
	sqlite3_stmt *res;
	char *blog_entry;
	char buffer[PATH_MAX];
	char *blog_subject;
	char *err_msg = 0;

	s_printf(get_string(285));
	s_readstring(buffer, 64);
	s_printf("\r\n");

	if (strlen(buffer) == 0) {
		s_printf(get_string(39));
		return;
	}

	blog_subject = strdup(buffer);

	blog_entry = external_editor(gUser, "No-One", "No-One", NULL, 0, "No-One", "Blog Editor", 0, 1);

	if (blog_entry != NULL) {
		snprintf(buffer, PATH_MAX, "%s/blog.sq3", conf.bbs_path);
		rc = sqlite3_open(buffer, &db);

		if (rc != SQLITE_OK) {
			dolog("Cannot open database: %s", sqlite3_errmsg(db));
			free(blog_entry);
			free(blog_subject);
			return;
		}
		sqlite3_busy_timeout(db, 5000);
		rc = sqlite3_exec(db, csql, 0, 0, &err_msg);
		if (rc != SQLITE_OK) {
			dolog("SQL error: %s", err_msg);
			sqlite3_free(err_msg);
			sqlite3_close(db);
			free(blog_entry);
			free(blog_subject);
			return;
		}

		rc = sqlite3_prepare_v2(db, isql, -1, &res, 0);

		if (rc == SQLITE_OK) {
			sqlite3_bind_text(res, 1, gUser->loginname, -1, 0);
			sqlite3_bind_text(res, 2, blog_subject, -1, 0);
			sqlite3_bind_text(res, 3, blog_entry, -1, 0);
			sqlite3_bind_int(res, 4, time(NULL));
		} else {
			dolog("Failed to execute statement: %s", sqlite3_errmsg(db));
			sqlite3_finalize(res);
			sqlite3_close(db);
			free(blog_entry);
			free(blog_subject);
			return;
		}
		sqlite3_step(res);

		sqlite3_finalize(res);
		sqlite3_close(db);
		free(blog_entry);
		free(blog_subject);
		return;
	}
	free(blog_subject);
}
