/**
 * SMSD message monitor program
 */
/* Copyright (c) 2009 - 2018 Michal Cihar <michal@cihar.com> */
/* Licensend under GNU GPL 2 */

#include <gammu-smsd.h>
#include <assert.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#ifndef WIN32
#include <unistd.h>
#endif
#ifdef HAVE_GETOPT_LONG
#include <getopt.h>
#endif

#include "common.h"
#include "log.h"

#if !defined(WIN32) && (defined(HAVE_GETOPT) || defined(HAVE_GETOPT_LONG))
#define HAVE_DEFAULT_CONFIG
const char default_config[] = "/etc/gammu-smsdrc";
#endif

volatile gboolean terminate = FALSE;
int delay_seconds = 20;
int limit_loops = -1;
gboolean compact = FALSE;

void smsd_interrupt(int signum)
{
	terminate = TRUE;
}

NORETURN void version(void)
{
	printf("Gammu-smsd-monitor version %s\n", GAMMU_VERSION);
	printf("Compiled in features:\n");
	printf("OS support:\n");
#ifdef HAVE_SHM
	printf("  - %s\n", "SHM");
#endif
#ifdef HAVE_GETOPT
	printf("  - %s\n", "GETOPT");
#endif
#ifdef HAVE_GETOPT_LONG
	printf("  - %s\n", "GETOPT_LONG");
#endif
	printf("Backend services:\n");
	printf("  - %s\n", "NULL");
	printf("  - %s\n", "FILES");
#ifdef HAVE_MYSQL_MYSQL_H
	printf("  - %s\n", "MYSQL");
#endif
#ifdef HAVE_POSTGRESQL_LIBPQ_FE_H
	printf("  - %s\n", "POSTGRESQL");
#endif
#ifdef LIBDBI_FOUND
	printf("  - %s\n", "DBI");
#endif
#ifdef ODBC_FOUND
	printf("  - %s\n", "ODBC");
#endif
	printf("\n");
	printf("Copyright (C) 2003 - 2018 Michal Cihar <michal@cihar.com> and other authors.\n");
	printf("\n");
	printf("License GPLv2: GNU GPL version 2 <https://spdx.org/licenses/GPL-2.0>.\n");
	printf("This is free software: you are free to change and redistribute it.\n");
	printf("There is NO WARRANTY, to the extent permitted by law.\n");
	printf("\n");
	printf("Check <https://wammu.eu/gammu/> for updates.\n");
	printf("\n");
	exit(0);
}

#ifdef HAVE_GETOPT_LONG
#define print_option(name, longname, help) \
	printf("-%s / --%s - %s\n", name, longname, help);
#define print_option_param(name, longname, paramname, help) \
	printf("-%s / --%s %s - %s\n", name, longname, paramname, help);
#else
#define print_option(name, longname, help) \
	printf("-%s - %s\n", name, help);
#define print_option_param(name, longname, paramname, help) \
	printf("-%s %s - %s\n", name, paramname, help);
#endif

void help(void)
{
	printf("usage: gammu-smsd-monitor [OPTION]...\n");
	printf("options:\n");
	print_option("h", "help", "shows this help");
	print_option("v", "version", "shows version information");
	print_option("C", "csv", "CSV output");
	print_option_param("c", "config", "CONFIG_FILE",
			   "defines path to config file");
	print_option_param("d", "delay", "DELAY",
			   "delay in seconds between loops");
	print_option_param("n", "loops", "NUMBER",
			   "number of loops");
	print_option("l", "use-log", "use logging configuration from config file");
	print_option("L", "no-use-log", "do not use logging configuration from config file (default)");
}

NORETURN void wrong_params(void)
{
	fprintf(stderr, "Invalid parameter, use -h for help.\n");
	exit(1);
}

void process_commandline(int argc, char **argv, SMSD_Parameters * params)
{
	int opt;

#ifdef HAVE_GETOPT_LONG
	struct option long_options[] = {
		{"help", 0, 0, 'h'},
		{"version", 0, 0, 'v'},
		{"config", 1, 0, 'c'},
		{"delay", 1, 0, 'd'},
		{"loops", 1, 0, 'n'},
		{"use-log", 0, 0, 'l'},
		{"no-use-log", 0, 0, 'L'},
		{0, 0, 0, 0}
	};
	int option_index;

	while ((opt =
		getopt_long(argc, argv, "+hvc:d:n:ClL", long_options,
			    &option_index)) != -1) {
#elif defined(HAVE_GETOPT)
	while ((opt = getopt(argc, argv, "+hvc:d:n:ClL")) != -1) {
#else
	/* Poor mans getopt replacement */
	int i;

#define optarg argv[++i]

	for (i = 1; i < argc; i++) {
		if (strlen(argv[i]) != 2 || argv[i][0] != '-') {
			wrong_params();
		}
		opt = argv[i][1];
#endif
		switch (opt) {
			case 'c':
				params->config_file = optarg;
				break;
			case 'v':
				version();
				break;
			case 'C':
				compact = TRUE;
				break;
			case 'd':
				delay_seconds = atoi(optarg);
				break;
			case 'n':
				limit_loops = atoi(optarg);
				break;
			case 'l':
				params->use_log = TRUE;
				break;
			case 'L':
				params->use_log = FALSE;
				break;
			case '?':
				wrong_params();
			case 'h':
				help();
				exit(0);
			default:
				fprintf(stderr, "Parameter -%c not known!\n", opt);
				wrong_params();
				break;
		}
	}

#if defined(HAVE_GETOPT) || defined(HAVE_GETOPT_LONG)
	if (optind < argc) {
		wrong_params();
	}
#endif

	return;

}

#ifndef WIN32
#endif

static void print_status(GSM_SMSDConfig *config, const GSM_SMSDStatus *status,
			 gboolean use_log)
{
	if (compact) {
		printf("%s;%s;%s;%s;%d;%d;%d;%d;%d\n",
		       status->Client,
		       status->PhoneID,
		       status->IMEI,
		       status->IMSI,
		       status->Sent,
		       status->Received,
		       status->Failed,
		       status->Charge.BatteryPercent,
		       status->Network.SignalPercent);
		fflush(stdout);
	} else if (use_log) {
		SMSD_Log(DEBUG_INFO, config,
			 "Status: Client=\"%s\", PhoneID=\"%s\", IMEI=\"%s\", IMSI=\"%s\", Sent=%d, Received=%d, Failed=%d, BatteryPercent=%d, NetworkSignal=%d",
			 status->Client,
			 status->PhoneID,
			 status->IMEI,
			 status->IMSI,
			 status->Sent,
			 status->Received,
			 status->Failed,
			 status->Charge.BatteryPercent,
			 status->Network.SignalPercent);
	} else {
		printf("Client: %s\n", status->Client);
		printf("PhoneID: %s\n", status->PhoneID);
		printf("IMEI: %s\n", status->IMEI);
		printf("IMSI: %s\n", status->IMSI);
		printf("Sent: %d\n", status->Sent);
		printf("Received: %d\n", status->Received);
		printf("Failed: %d\n", status->Failed);
		printf("BatterPercent: %d\n", status->Charge.BatteryPercent);
		printf("NetworkSignal: %d\n", status->Network.SignalPercent);
		printf("\n");
		fflush(stdout);
	}
}

int main(int argc, char **argv)
{
	GSM_Error error;
	GSM_SMSDConfig *config;
	GSM_SMSDStatus status;
	const char program_name[] = "gammu-smsd-monitor";
	SMSD_Parameters params = {
		NULL,
		NULL,
		-1,
		-1,
		NULL,
		NULL,
		FALSE,
		FALSE,
		FALSE,
		FALSE,
		FALSE,
		FALSE,
		FALSE,
		FALSE,
		FALSE,
		0
	};


	/*
	 * We don't need gettext, but need to set locales so that
	 * charset conversion works.
	 */
	GSM_InitLocales(NULL);

	process_commandline(argc, argv, &params);

	if (params.config_file == NULL) {
#ifdef HAVE_DEFAULT_CONFIG
		params.config_file = default_config;
#else
		fprintf(stderr, "No config file specified!\n");
		help();
		exit(1);
#endif
	}

	signal(SIGINT, smsd_interrupt);
	signal(SIGTERM, smsd_interrupt);

	config = SMSD_NewConfig(program_name);
	assert(config != NULL);

	error = SMSD_ReadConfig(params.config_file, config, params.use_log);
	if (error != ERR_NONE) {
		printf("Failed to read config: %s\n", GSM_ErrorString(error));
		SMSD_FreeConfig(config);
		return 2;
	}
	SMSD_EnableGlobalDebug(config);

	while (!terminate && (limit_loops == -1 || limit_loops-- > 0)) {
		error = SMSD_GetStatus(config, &status);
		if (error != ERR_NONE) {
			printf("Failed to get status: %s\n", GSM_ErrorString(error));
			SMSD_FreeConfig(config);
			return 3;
		}
		print_status(config, &status, params.use_log);
		sleep(delay_seconds);
	}

	SMSD_FreeConfig(config);

	return 0;
}

/* How should editor hadle tabs in this file? Add editor commands here.
 * vim: noexpandtab sw=8 ts=8 sts=8:
 */
