/*
 * xlru_mex.cpp
 *
 */

#include "mex.h"

#include "xlru_manager.h"

#include "xlru_psm.h"
#include "xlru_pps.h"
#include "xlru_lcu.h"

#include "xlru_comm.h"

#ifndef _TMS320C6X
#ifdef __GNUC__
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
#endif
#endif

static int show_unit;

static int lcu_map;
static int pps_map;
static int psm_map;
static int q_udp_mon;

static const mex_cmd_param_descriptor_t start_table[] =
{
		{ "psm", "PSM channel", 0, &psm_map, &mex_mt_int },
		{ "pps", "PPS Channel", 0, &pps_map, &mex_mt_int },
		{ "lcu", "LCU Channel", 0, &lcu_map, &mex_mt_int },

		{ "m", "enabled UDP monitor", mex_cmd_qualifier, &q_udp_mon, &mex_mt_uint},

#if 0
		{ "c", "copy configuration", mex_cmd_qualifier, &ip_remap_copy, &mex_mt_uint},
		{ "d", "enable DAC", mex_cmd_qualifier, &ip_dac_ena, &mex_mt_uint},
		{ "p", "copy palet", mex_cmd_qualifier, &ip_palet_copy, &mex_mt_uint},
#endif
		MEX_TABLE_END
};

extern void xlru_channel_map(unsigned int psm, unsigned int pps, unsigned int lcu);

static mex_res_t Cmd_Start(void)
{
	xlru_channel_map(psm_map, pps_map, lcu_map);

	if (mex_param_is_present(&q_udp_mon))
	{
		xlru_comm_udp_monitor_enable(true); //q_udp_mon>0);
	}

  return mex_ok;
}

static const mex_cmd_descriptor_t cmd_start=
{ "start", "start XLRU manager", (mex_cmd_handler_t) Cmd_Start, start_table};


static const mex_cmd_param_descriptor_t show_table[] =
{
		{ "unit", "unit details", 0, &show_unit, &mex_mt_int },
		MEX_TABLE_END
};

static void show_basic_status(const char* name, const XLruManager::unit_status_t& sts, const xlru_counter_t& cntr)
{
	mex_printf(" %s: %s T=%s, link=%s (%5u/%5u) le=%5u (%12.12s)\n", name,
		    sts.basicStatus.unitOk ? "OK  " : "FAIL",
		    sts.basicStatus.overtempHazard ? "HAZARD" : (sts.basicStatus.overtempWarning ? "WARN  " : "NORMAL"),
			sts.commStatus.linkUp ? "UP  " : "DOWN", //psm.status.commStatus.commDeviceOk ? "OK  " : "FAIL",
			sts.commStatus.good_messages & 0x0FFFF,
			sts.commStatus.error_messages & 0xFFFF,
			cntr.rx_mess_error & 0xFFFF, cntr.last_error);
}

static mex_res_t Cmd_Status(void)
{
	if (mex_param_loop())
		mex_page_loop_init(1);
	do
    {
    	mex_page_loop_top();

		const XLruManager::manager_status_t& m=XLruManager::managerStatus();
		mex_printf("OUT: %5u (%5u), IN: %5u (%5u/%5u), b: %5u (%5u), \n",
				m.poroduce_messages & 0x0FFFF,
				m.transmitted_bytes & 0x0FFFF,
				m.good_messages & 0x0FFFF,
				m.error_messages & 0x0FFFF,
				m.received_messages & 0x0FFFF,
				m.received_bytes & 0x0FFFF,
				m.received_garbage & 0x0FFFF);
		const XLruManager::psm_status_t& psm=XLruManager::psmStatus();
		show_basic_status("PSM", psm.status, xlru_psm::xlru_counter);

		const XLruManager::pps_status_t& pps=XLruManager::ppsStatus();
		show_basic_status("PPS", pps.status, xlru_pps::xlru_counter);

		const XLruManager::lcu_status_t& lcu=XLruManager::lcuStatus();
		show_basic_status("LCU", lcu.status, xlru_lcu::xlru_counter);

		if (mex_param_is_present(&show_unit))
		{
			switch(show_unit)
			{
			case 0:
				xlru_psm::xlru_display(mex_printf);
				break;
			case 1:
				xlru_pps::xlru_display(mex_printf);
				break;
			case 2:
				xlru_lcu::xlru_display(mex_printf);
				break;
			default:
				break;
			}
		}
    } while (mex_page_loop_end(0, 0) != mex_page_event_quit);

    return mex_ok;
}

static const mex_cmd_descriptor_t cmd_status=
{ "status", "XLRU status", (mex_cmd_handler_t) Cmd_Status, show_table};

static mex_res_t Cmd_Recycle(void)
{
	XLruManager::psmRecycle(true);

    return mex_ok;
}

static const mex_cmd_descriptor_t cmd_recycle=
{ "recycle", "PSM recyle", (mex_cmd_handler_t) Cmd_Recycle, 0};

static mex_res_t Cmd_Poweroff(void)
{
	XLruManager::psmPowerDown(true);

    return mex_ok;
}

static const mex_cmd_descriptor_t cmd_poweroff=
{ "psmoff", "PSM OFF", (mex_cmd_handler_t) Cmd_Poweroff, 0};


static void oob_handler(char c)
{
	mex_putchar_nomore(c);
}

static mex_res_t Cmd_Bridge(void)
{
	XLruManager::setOutOfBandDataHandler(oob_handler);
	for(;;)
	{
		int c=mex_getch();
		if (c=='Q')
			break;
		if (c=='\r')
			XLruManager::injectOutofBandData('\n');
		else
			XLruManager::injectOutofBandData(c);
	}
	XLruManager::setOutOfBandDataHandler(0);

	return mex_ok;
}

static const mex_cmd_descriptor_t cmd_bridge=
{ "bridge", "XLRU bridge", (mex_cmd_handler_t) Cmd_Bridge, 0};

static const mex_mt_object_t xlru_str_lists[]=
{
  MEX_CMD_REF("start", &cmd_start),
  MEX_CMD_REF("status", &cmd_status),
  MEX_CMD_REF("bridge", &cmd_bridge),
  MEX_CMD_REF("recyle", &cmd_recycle),
  MEX_CMD_REF("psmoff", &cmd_poweroff),


  {0}
};

static const mex_mt_struct_t xlru_mt=
{{"xlru", 0, &mex_mt_struct_methods}, xlru_str_lists};


static mex_mt_object_t xlru_obj={
  0, "xlru", &MEX_MT_CAST(xlru_mt), 0
};


void xlru_mex_initialize()
{
	mex_object_register(mex_object_root(), &xlru_obj);
}



