/* location-manual.c -- Manual location provider source
   This file is part of redshift-ng.

   redshift-ng 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 3 of the License, or
   (at your option) any later version.

   redshift-ng 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.

   You should have received a copy of the GNU General Public License
   along with redshift-ng.  If not, see <http://www.gnu.org/licenses/>.

   Copyright (c) 2010-2017  Jon Lund Steffensen <jonlst@gmail.com>
   Copyright (c) 2025       Mattias Andrée <m@maandree.se>
*/
#include "common.h"


struct location_state {
	struct location loc;
};


static int
location_manual_init(struct location_state **state)
{
	*state = emalloc(sizeof(**state));
	(*state)->loc.lat = NAN;
	(*state)->loc.lon = NAN;
	return 0;
}

static int
location_manual_start(struct location_state *state)
{
	if (isnan(state->loc.lat) || isnan(state->loc.lon))
		eprintf(_("Latitude and longitude must be set."));
	return 0;
}

static void
location_manual_free(struct location_state *state)
{
	free(state);
}

static void
location_manual_print_help(FILE *f)
{
	fputs(_("Specify location manually.\n"), f);
	fputs("\n", f);

	/* TRANSLATORS: Manual location help output
	   left column must not be translated */
	fputs(_("  lat=N\t\tLatitude\n"
		"  lon=N\t\tLongitude\n"), f);
	fputs("\n", f);
	fputs(_("Both values are expected to be floating point numbers,\n"
		"negative values representing west / south, respectively.\n"), f);
	fputs("\n", f);
}

static int
location_manual_set_option(struct location_state *state, const char *key, const char *value)
{
	/* Parse float value */
	char *end;
	double v;

	errno = 0;
	v = strtod(value, &end);
	if (errno || *end) {
		weprintf(_("Malformed argument."));
		return -1;
	}

	if (!strcasecmp(key, "lat")) {
		state->loc.lat = v;
	} else if (!strcasecmp(key, "lon")) {
		state->loc.lon = v;
	} else {
		weprintf(_("Unknown method parameter: `%s'."), key);
		return -1;
	}

	return 0;
}

static int
location_manual_get_fd(struct location_state *state)
{
	(void) state;
	return -1;
}

static int
location_manual_handle(struct location_state *state, struct location *location, int *available)
{
	*location = state->loc;
	*available = 1;
	return 0;
}


const struct location_provider manual_location_provider = {
	"manual",
	&location_manual_init,
	&location_manual_start,
	&location_manual_free,
	&location_manual_print_help,
	&location_manual_set_option,
	&location_manual_get_fd,
	&location_manual_handle
};