/* (C) 2015 by Harald Welte <laforge@gnumonks.org>
 *
 * All Rights Reserved
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <string.h>

#include <osmocom/core/utils.h>
#include <osmocom/crypt/auth.h>

#include <sqlite3.h>

#include "logging.h"
#include "db.h"

#define LOGHLR(imsi, level, fmt, args ...)	LOGP(DAUC, level, "%s: " fmt, imsi, ## args)

#define SL3_TXT(x, stmt, idx)					do {	\
		const char *_txt = (const char *) sqlite3_column_text(stmt, idx);	\
		if (_txt)						\
			strncpy(x, _txt, sizeof(x));			\
			x[sizeof(x)-1] = '\0';				\
		} while (0)

int db_subscr_get(struct db_context *dbc, const char *imsi,
		  struct hlr_subscriber *subscr)
{
	sqlite3_stmt *stmt = dbc->stmt[SEL_BY_IMSI];
	int rc, ret = 0;

	rc = sqlite3_bind_text(stmt, 1, imsi, -1, SQLITE_STATIC);
	if (rc != SQLITE_OK) {
		LOGHLR(imsi, LOGL_ERROR, "Error binding IMSI: %d\n", rc);
		return -1;
	}

	/* execute the statement */
	rc = sqlite3_step(stmt);
	if (rc != SQLITE_ROW) {
		LOGHLR(imsi, LOGL_ERROR, "Error executing SQL: %d\n", rc);
		ret = -2;
		goto out;
	}

	/* obtain the various columns */
	subscr->id = sqlite3_column_int64(stmt, 0);
	SL3_TXT(subscr->imsi, stmt, 1);
	SL3_TXT(subscr->msisdn, stmt, 2);
	/* FIXME: These should all be BLOBs as they might contain NUL */
	SL3_TXT(subscr->vlr_number, stmt, 3);
	SL3_TXT(subscr->sgsn_number, stmt, 4);
	SL3_TXT(subscr->sgsn_address, stmt, 5);
	subscr->periodic_lu_timer = sqlite3_column_int(stmt, 6);
	subscr->periodic_rau_tau_timer = sqlite3_column_int(stmt, 7);
	subscr->nam_cs = sqlite3_column_int(stmt, 8);
	subscr->nam_ps = sqlite3_column_int(stmt, 9);
	subscr->lmsi = sqlite3_column_int(stmt, 10);
	subscr->ms_purged_cs = sqlite3_column_int(stmt, 11);
	subscr->ms_purged_ps = sqlite3_column_int(stmt, 12);

out:
	/* remove bindings and reset statement to be re-executed */
	rc = sqlite3_clear_bindings(stmt);
	if (rc != SQLITE_OK) {
		LOGP(DAUC, LOGL_ERROR, "Error clerearing bindings: %d\n", rc);
	}
	rc = sqlite3_reset(stmt);
	if (rc != SQLITE_OK) {
		LOGP(DAUC, LOGL_ERROR, "Error in sqlite3_reset: %d\n", rc);
	}

	return ret;
}

int db_subscr_lu(struct db_context *dbc,
		 const struct hlr_subscriber *subscr,
		 const char *vlr_or_sgsn_number, bool lu_is_ps)
{
	sqlite3_stmt *stmt = dbc->stmt[UPD_VLR_BY_ID];
	const char *txt;
	int rc, ret = 0;

	if (lu_is_ps) {
		stmt = dbc->stmt[UPD_SGSN_BY_ID];
		txt = subscr->sgsn_number;
	} else {
		stmt = dbc->stmt[UPD_VLR_BY_ID];
		txt = subscr->vlr_number;
	}

	rc = sqlite3_bind_int64(stmt, 1, subscr->id);
	if (rc != SQLITE_OK) {
		LOGP(DAUC, LOGL_ERROR, "Error binding ID: %d\n", rc);
		return -1;
	}

	rc = sqlite3_bind_text(stmt, 2, txt, -1, SQLITE_STATIC);
	if (rc != SQLITE_OK) {
		LOGP(DAUC, LOGL_ERROR, "Error binding VLR/SGSN Number: %d\n", rc);
		ret = -2;
		goto out;
	}

	/* execute the statement */
	rc = sqlite3_step(stmt);
	if (rc != SQLITE_DONE) {
		LOGP(DAUC, LOGL_ERROR, "Error updating SQN: %d\n", rc);
		ret = -3;
		goto out;
	}
out:
	/* remove bindings and reset statement to be re-executed */
	rc = sqlite3_clear_bindings(stmt);
	if (rc != SQLITE_OK) {
		LOGP(DAUC, LOGL_ERROR, "Error clerearing bindings: %d\n", rc);
	}
	rc = sqlite3_reset(stmt);
	if (rc != SQLITE_OK) {
		LOGP(DAUC, LOGL_ERROR, "Error in sqlite3_reset: %d\n", rc);
	}

	return ret;
}

int db_subscr_purge(struct db_context *dbc, const char *imsi, bool is_ps)
{
	sqlite3_stmt *stmt = dbc->stmt[UPD_VLR_BY_ID];
	int rc, ret = 1;

	if (is_ps)
		stmt = dbc->stmt[UPD_PURGE_PS_BY_IMSI];
	else
		stmt = dbc->stmt[UPD_PURGE_CS_BY_IMSI];

	rc = sqlite3_bind_text(stmt, 1, imsi, -1, SQLITE_STATIC);
	if (rc != SQLITE_OK) {
		LOGP(DAUC, LOGL_ERROR, "Error binding IMSI %s: %d\n", imsi, rc);
		ret = -1;
		goto out;
	}

	/* execute the statement */
	rc = sqlite3_step(stmt);
	if (rc != SQLITE_DONE) {
		LOGP(DAUC, LOGL_ERROR, "Error setting Purged: %d\n", rc);
		ret = -2;
		goto out;
	}
	/* FIXME: return 0 in case IMSI not known */
out:
	/* remove bindings and reset statement to be re-executed */
	rc = sqlite3_clear_bindings(stmt);
	if (rc != SQLITE_OK) {
		LOGP(DAUC, LOGL_ERROR, "Error clearing bindings: %d\n", rc);
	}
	rc = sqlite3_reset(stmt);
	if (rc != SQLITE_OK) {
		LOGP(DAUC, LOGL_ERROR, "Error in sqlite3_reset: %d\n", rc);
	}

	return ret;
}
