/* (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 <errno.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;

	if (!db_bind_imsi(stmt, imsi))
		return -EINVAL;

	/* execute the statement */
	rc = sqlite3_step(stmt);
	if (rc != SQLITE_ROW) {
		LOGHLR(imsi, LOGL_ERROR, "Error executing SQL: %d\n", rc);
		ret = -ENOEXEC;
		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:
	db_remove_reset(stmt);

	return ret;
}

int db_subscr_ps(struct db_context *dbc, const char *imsi, bool enable)
{
	sqlite3_stmt *stmt =
		dbc->stmt[enable ? SET_NAM_PS_BY_IMSI : UNSET_NAM_PS_BY_IMSI];
	int rc;

	if (!db_bind_imsi(stmt, imsi))
		return -EINVAL;

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

	rc = sqlite3_changes(dbc->db); /* verify execution result */
	if (rc != 1) {
		LOGHLR(imsi, LOGL_ERROR, "SQL modified %d rows (expected 1)\n",
		       rc);
		rc = -EINVAL;
	}

	db_remove_reset(stmt);
	return rc;
}

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 -EINVAL;
	}

	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 = -EBADMSG;
		goto out;
	}

	/* execute the statement */
	rc = sqlite3_step(stmt);
	if (rc != SQLITE_DONE) {
		LOGP(DAUC, LOGL_ERROR, "Error updating SQN: %d\n", rc);
		ret = -ENOEXEC;
	}
out:
	db_remove_reset(stmt);

	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];

	if (!db_bind_imsi(stmt, imsi))
		return -EINVAL;

	/* execute the statement */
	rc = sqlite3_step(stmt);
	if (rc != SQLITE_DONE) {
		LOGP(DAUC, LOGL_ERROR, "Error setting Purged: %d\n", rc);
		ret = -ENOEXEC;
	}
	/* FIXME: return 0 in case IMSI not known */

	db_remove_reset(stmt);

	return ret;
}
