/* (C) 2018-2020 by Harald Welte <laforge@gnumonks.org>
 *
 * All Rights Reserved
 *
 * SPDX-License-Identifier: GPL-2.0+
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 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 General Public License for more details.
 *
 */

/* This file contains code shared among all remsim client applications,
 * including the ifd-handler, which is not an executable program with a main()
 * function or command line parsing, but a shared library */

#include <errno.h>
#include <string.h>

#include <talloc.h>

#include <osmocom/core/fsm.h>
#include <osmocom/core/utils.h>
#include <osmocom/core/logging.h>

#include "rspro_util.h"
#include "client.h"
#include "debug.h"

struct client_config *client_config_init(void *ctx)
{
	struct client_config *cfg = talloc_zero(ctx, struct client_config);
	if (!cfg)
		return NULL;

	cfg->server_host = talloc_strdup(cfg, "127.0.0.1");
	cfg->server_port = 9998;
	cfg->client_id = -1;
	cfg->client_slot = -1;
	cfg->gsmtap_host = talloc_strdup(cfg, "127.0.0.1");
	cfg->keep_running = false;

	cfg->usb.vendor_id = -1;
	cfg->usb.product_id = -1;
	cfg->usb.config_id = -1;
	cfg->usb.if_num = -1;
	cfg->usb.altsetting = 0;
	cfg->usb.addr = -1;
	cfg->usb.path = NULL;

	cfg->atr.data[0] = 0x3B;
	cfg->atr.data[1] = 0x00; // the shortest simplest ATR possible
	cfg->atr.len = 2;
	cfg->atr_ignore_rspro = false;

	return cfg;
};

static int bankd_handle_rx(struct rspro_server_conn *bankdc, const RsproPDU_t *pdu)
{
	struct bankd_client *bc = bankdc2bankd_client(bankdc);

	switch (pdu->msg.present) {
	case RsproPDUchoice_PR_connectClientRes:
		if (pdu->msg.choice.connectClientRes.identity.type != ComponentType_remsimBankd) {
			LOGPFSML(bankdc->fi, LOGL_ERROR, "Server connection to a ComponentType(%ld) != RemsimBankd? "
				 "Check your IP/Port configuration\n",
				 pdu->msg.choice.connectClientRes.identity.type);
			osmo_fsm_inst_dispatch(bankdc->fi, SRVC_E_DISCONNECT, NULL);
			return -1;
		}
		/* Store 'identity' of bankd to in peer_comp_id */
		rspro_comp_id_retrieve(&bankdc->peer_comp_id, &pdu->msg.choice.connectClientRes.identity);
		osmo_fsm_inst_dispatch(bankdc->fi, SRVC_E_CLIENT_CONN_RES, (void *) pdu);
		break;
	case RsproPDUchoice_PR_tpduCardToModem:
		return osmo_fsm_inst_dispatch(bc->main_fi, MF_E_BANKD_TPDU, (void *) pdu);
	case RsproPDUchoice_PR_setAtrReq:
		return osmo_fsm_inst_dispatch(bc->main_fi, MF_E_BANKD_ATR, (void *) pdu);
	case RsproPDUchoice_PR_bankSlotStatusInd:
		return osmo_fsm_inst_dispatch(bc->main_fi, MF_E_BANKD_SLOT_STATUS, (void *) pdu);
	default:
		LOGPFSML(bankdc->fi, LOGL_ERROR, "Unknown/Unsupported RSPRO PDU %s\n",
			 rspro_msgt_name(pdu));
		return -1;
	}

	return 0;
}

/* handle incoming messages from server */
static int srvc_handle_rx(struct rspro_server_conn *srvc, const RsproPDU_t *pdu)
{
	struct bankd_client *bc = srvc2bankd_client(srvc);
	RsproPDU_t  *resp;

	switch (pdu->msg.present) {
	case RsproPDUchoice_PR_connectClientRes:
		if (pdu->msg.choice.connectClientRes.identity.type != ComponentType_remsimServer) {
			LOGPFSML(srvc->fi, LOGL_ERROR, "Server connection to a ComponentType(%ld) != RemsimServer? "
				 "Check your IP/Port configuration\n",
				 pdu->msg.choice.connectClientRes.identity.type);
			osmo_fsm_inst_dispatch(srvc->fi, SRVC_E_DISCONNECT, NULL);
			return -1;
		}
		/* Store 'identity' of server in srvc->peer_comp_id */
		rspro_comp_id_retrieve(&srvc->peer_comp_id, &pdu->msg.choice.connectClientRes.identity);
		osmo_fsm_inst_dispatch(srvc->fi, SRVC_E_CLIENT_CONN_RES, (void *) pdu);
		break;
	case RsproPDUchoice_PR_configClientIdReq:
		/* store/set the clientID as instructed by the server */
		if (!srvc->clslot)
			srvc->clslot = talloc_zero(srvc, ClientSlot_t);
		*srvc->clslot = pdu->msg.choice.configClientIdReq.clientSlot;
		if (!bc->bankd_conn.clslot)
			bc->bankd_conn.clslot = talloc_zero(bc, ClientSlot_t);
		*bc->bankd_conn.clslot = *bc->srv_conn.clslot;
		/* send response to server */
		resp = rspro_gen_ConfigClientIdRes(ResultCode_ok);
		server_conn_send_rspro(srvc, resp);
		break;
	case RsproPDUchoice_PR_configClientBankReq:
		osmo_fsm_inst_dispatch(bc->main_fi, MF_E_SRVC_CONFIG_BANK, (void *) pdu);
		break;
	default:
		LOGPFSML(srvc->fi, LOGL_ERROR, "Unknown/Unsupported RSPRO PDU type: %s\n",
			 rspro_msgt_name(pdu));
		return -1;
	}

	return 0;
}

struct bankd_client *remsim_client_create(void *ctx, const char *name, const char *software,
					  struct client_config *cfg)
{
	struct bankd_client *bc = talloc_zero(ctx, struct bankd_client);
	struct rspro_server_conn *srvc, *bankdc;
	int rc;

	if (!bc)
		return NULL;

	bc->cfg = cfg;

	bc->main_fi = main_fsm_alloc(bc, bc);
	if (!bc->main_fi) {
		LOGP(DMAIN, LOGL_FATAL, "Unable to create main client FSM: %s\n", strerror(errno));
		exit(1);
	}

	remsim_client_set_clslot(bc, cfg->client_id, cfg->client_slot);

	/* create and [attempt to] establish connection to remsim-server */
	srvc = &bc->srv_conn;
	srvc->server_host = cfg->server_host;
	srvc->server_port = cfg->server_port;
	srvc->handle_rx = srvc_handle_rx;
	srvc->own_comp_id.type = ComponentType_remsimClient;
	OSMO_STRLCPY_ARRAY(srvc->own_comp_id.name, name);
	OSMO_STRLCPY_ARRAY(srvc->own_comp_id.software, software);
	OSMO_STRLCPY_ARRAY(srvc->own_comp_id.sw_version, PACKAGE_VERSION);

	rc = server_conn_fsm_alloc(bc, srvc);
	if (rc < 0) {
		LOGP(DMAIN, LOGL_FATAL, "Unable to create Server conn FSM: %s\n", strerror(errno));
		exit(1);
	}
	osmo_fsm_inst_change_parent(srvc->fi, bc->main_fi, MF_E_SRVC_LOST);
	srvc->parent_conn_evt = MF_E_SRVC_CONNECTED;
	srvc->parent_disc_evt = MF_E_SRVC_LOST;

	bankdc = &bc->bankd_conn;
	/* server_host / server_port are configured from remsim-server */
	bankdc->handle_rx = bankd_handle_rx;
	memcpy(&bankdc->own_comp_id, &srvc->own_comp_id, sizeof(bankdc->own_comp_id));
	rc = server_conn_fsm_alloc(bc, bankdc);
	if (rc < 0) {
		LOGP(DMAIN, LOGL_FATAL, "Unable to connect bankd conn FSM: %s\n", strerror(errno));
		exit(1);
	}
	osmo_fsm_inst_update_id(bankdc->fi, "bankd");
	osmo_fsm_inst_change_parent(bankdc->fi, bc->main_fi, MF_E_BANKD_LOST);
	bankdc->parent_conn_evt = MF_E_BANKD_CONNECTED;
	bankdc->parent_disc_evt = MF_E_BANKD_LOST;

	return bc;
}

void remsim_client_set_clslot(struct bankd_client *bc, int client_id, int slot_nr)
{
	if (!bc->srv_conn.clslot) {
		bc->srv_conn.clslot = talloc_zero(bc, ClientSlot_t);
		OSMO_ASSERT(bc->srv_conn.clslot);
	}

	if (!bc->bankd_conn.clslot) {
		bc->bankd_conn.clslot = talloc_zero(bc, ClientSlot_t);
		OSMO_ASSERT(bc->bankd_conn.clslot);
	}

	if (client_id >= 0) {
		bc->srv_conn.clslot->clientId = client_id;
		bc->bankd_conn.clslot->clientId = client_id;
	}

	if (slot_nr >= 0) {
		bc->srv_conn.clslot->slotNr = slot_nr;
		bc->bankd_conn.clslot->slotNr = slot_nr;
	}
}
