/* OsmoHLR Control Interface implementation */

/* (C) 2017 sysmocom s.f.m.c. GmbH <info@sysmocom.de>
 * All Rights Reserved
 *
 * Author: Max Suraev <msuraev@sysmocom.de>
 *
 * 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 <stdbool.h>

#include <osmocom/ctrl/control_cmd.h>
#include <osmocom/ctrl/control_if.h>
#include <osmocom/ctrl/ports.h>

#include "gsup_server.h"
#include "logging.h"
#include "db.h"
#include "hlr.h"
#include "luop.h"
#include "ctrl.h"

static int handle_cmd_ps(struct hlr *ctx, struct ctrl_cmd *cmd, bool enable)
{
	struct lu_operation *luop = NULL;
	struct osmo_gsup_conn *co;

	if (db_subscr_get_by_imsi(ctx->dbc, cmd->value, NULL) < 0) {
		cmd->reply = "Subscriber Unknown in HLR";
		return CTRL_CMD_ERROR;
	}

	if (db_subscr_ps(ctx->dbc, cmd->value, enable) < 0) {
		cmd->reply = "Error updating DB";
		return CTRL_CMD_ERROR;
	}

	/* FIXME: only send to single SGSN where latest update for IMSI came from */
	if (!enable) {
		llist_for_each_entry(co, &ctx->gs->clients, list) {
			luop = lu_op_alloc_conn(co);
			lu_op_fill_subscr(luop, ctx->dbc, cmd->value);
			lu_op_tx_del_subscr_data(luop);
		}
	}

	cmd->reply = "OK";

	return CTRL_CMD_REPLY;
}

CTRL_CMD_DEFINE_WO_NOVRF(enable_ps, "enable-ps");
static int set_enable_ps(struct ctrl_cmd *cmd, void *data)
{
	return handle_cmd_ps(data, cmd, true);
}

CTRL_CMD_DEFINE_WO_NOVRF(disable_ps, "disable-ps");
static int set_disable_ps(struct ctrl_cmd *cmd, void *data)
{
	return handle_cmd_ps(data, cmd, false);
}

CTRL_CMD_DEFINE_WO_NOVRF(status_ps, "status-ps");
static int set_status_ps(struct ctrl_cmd *cmd, void *data)
{
	struct hlr *ctx = data;
	struct lu_operation *luop = lu_op_alloc(ctx->gs);
	if (!luop) {
		cmd->reply = "Internal HLR error";
		return CTRL_CMD_ERROR;
	}

	if (!lu_op_fill_subscr(luop, ctx->dbc, cmd->value)) {
		cmd->reply = "Subscriber Unknown in HLR";
		return CTRL_CMD_ERROR;
	}

	cmd->reply = luop->subscr.nam_ps ? "1" : "0";

	return CTRL_CMD_REPLY;
}

int hlr_ctrl_cmds_install()
{
	int rc = 0;

	rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_enable_ps);
	rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_disable_ps);
	rc |= ctrl_cmd_install(CTRL_NODE_ROOT, &cmd_status_ps);

	return rc;
}

struct ctrl_handle *hlr_controlif_setup(struct hlr *ctx,
					struct osmo_gsup_server *gs)
{
	int rc;
	struct ctrl_handle *hdl = ctrl_interface_setup_dynip(ctx,
							     ctx->ctrl_bind_addr,
							     OSMO_CTRL_PORT_HLR,
							     NULL);
	if (!hdl)
		return NULL;

	rc = hlr_ctrl_cmds_install();
	if (rc) /* FIXME: close control interface? */
		return NULL;

	return hdl;
}
