/*
 * Copyright (C) 2022-2025 Seagull Developers
 *
 * Seagull is the legal property of its developers, whose names are too
 * numerous to list here. Please refer to the AUTHORS file distributed
 * with this source distribution
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, see <https://www.gnu.org/licenses/>.
 */

#include <sqlite3.h>

#include "seagulldb.h"

G_DEFINE_QUARK(seagull-db-error, seagull_db_error)

/******************************************************************************
 * Public API
 *****************************************************************************/
SeagullSqlite3 *
seagull_db_new_in_memory(GError **error) {
	return seagull_db_new_from_file(":memory:", error);
}

SeagullSqlite3 *
seagull_db_new_from_file(const char *filename, GError **error) {
	SeagullSqlite3 *db = NULL;
	int rc = SQLITE_OK;

	g_return_val_if_fail(filename != NULL, NULL);
	g_return_val_if_fail(filename[0] != '\0', NULL);

	rc = sqlite3_open(filename, &db);
	if(rc != SQLITE_OK) {
		if(db != NULL) {
			g_set_error(error,
			            SEAGULL_DB_ERROR,
			            SEAGULL_DB_ERROR_NEW_FAILED,
			            "failed to create database: %s",
			            sqlite3_errmsg(db));
			g_clear_pointer(&db, sqlite3_close);
		} else {
			g_set_error_literal(error,
			                    SEAGULL_DB_ERROR,
			                    SEAGULL_DB_ERROR_NEW_FAILED,
			                    "failed to create database: unknown error");
		}
	}

	return db;
}

SeagullSqlite3 *
seagull_db_new_from_uri(const char *uri, GError **error) {
	SeagullSqlite3 *db = NULL;
	int rc = SQLITE_OK;
	int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_URI;

	g_return_val_if_fail(uri != NULL, NULL);
	g_return_val_if_fail(uri[0] != '\0', NULL);

	rc = sqlite3_open_v2(uri, &db, flags, NULL);
	if(rc != SQLITE_OK) {
		if(db != NULL) {
			g_set_error(error,
			            SEAGULL_DB_ERROR,
			            SEAGULL_DB_ERROR_NEW_FAILED,
			            "failed to create database: %s",
			            sqlite3_errmsg(db));
			g_clear_pointer(&db, sqlite3_close);
		} else {
			g_set_error_literal(error,
			                    SEAGULL_DB_ERROR,
			                    SEAGULL_DB_ERROR_NEW_FAILED,
			                    "failed to create database: unknown error");
		}
	}

	return db;
}

gboolean
seagull_db_close(SeagullSqlite3 *db, GError **error) {
	int rc = SQLITE_OK;

	rc = sqlite3_close(db);
	if(rc == SQLITE_BUSY) {
		g_set_error_literal(error,
		                    SEAGULL_DB_ERROR,
		                    SEAGULL_DB_ERROR_CLOSE_FAILED,
		                    "the database is still in use");

		return FALSE;
	}

	return TRUE;
}
