/*
    Tucnak - VHF contest log
    Copyright (C) 2011-2023 Ladislav Vaiz <ok1zia@nagano.cz>

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    version 2 as published by the Free Software Foundation.

*/

#ifndef __ROTAR_H
#define __ROTAR_H

#include "header.h"

#include "oct8tor.h"

struct sdev;

#ifdef __GNUC__
#define TRROT(thr, m...) if (cfg->trace_sdev >= (thr ? 2 : 1)){ \
    GString *gs = g_string_new("ROT: "); \
    if (thr) g_string_append(gs, "        "); \
	g_string_append_printf(gs, m); \
	trace(1, "%s", gs->str); \
	g_string_free(gs, TRUE); \
}
#else
#define TRROT(thr, ...) if (cfg->trace_sdev >= (thr ? 2 : 1)){ \
    GString *gsxy = g_string_new("ROT: "); \
    if (thr) g_string_append(gsxy, "           "); \
	g_string_append_printf(gsxy, __VA_ARGS__); \
	trace(1, "%s", gsxy->str); \
	g_string_free(gsxy, TRUE); \
}
#endif

enum rot_type {
    ROT_NONE=0,
    ROT_OK1ZIA_TTYS=1,
    ROT_OK1ZIA_FTDI=2,
    ROT_HAMLIB=3,
    ROT_REMOTE=4,
#ifdef OCT8TOR
	ROT_OCT8TOR = 5
#endif
};

struct config_rotar{
    gint nr;

    /* common */
    gchar *rot_desc;
    enum rot_type rot_type;
    gchar *rot_filename;
    gchar *rot_hostname;
    gint rot_port;
    gint rot_vid, rot_pid;
    gchar *rot_serial;
    gint rot_timeout_ms, rot_beamwidth, rot_poll_ms;
	gint rot_offset;

    /* ok1zia */
    gint rot_saddr;

    /* hamlib */
    gint rot_model;
	gint rot_speed;

    /* remote */
    gchar *rot_rem_rotstr;
};


struct rotar{
    /* config */
    struct sdev *sdev;
#ifdef HAVE_HAMLIB
    ROT *rot;
#endif
#ifdef OCT8TOR
	struct oct8tor *oct;
#endif
    int step;      
    int rotchar; /* A, B, ... */
	char rotstr[2]; 
    int type;
    gchar *netid;
    gchar *desc;
    int beamwidth; /* in degrees */
	int offset; /* in degrees */
    
    /* device versions */
    int verh, verl, identa;
    
    /* state */
	int qtf; // tucnak value not affected by offset
	int oldqtf; // affected by offset
	int elev, oldelev;
//    int timer_id;           /* time between two command to prevent high cpu load */

    int color; /* color of arrow in polar map */
    int termcolor; /* color on terminal */
    gchar *rem_rotstr;
    int last_req;
#ifdef HAVE_HAMLIB
    GThread *hl_thread;
    int hl_azim, hl_elev, hl_stop;
    int hl_model;
    int hl_give_me_chance;
    int hl_thread_break;
	int rot_speed;
	elevation_t hl_lastelev;
#endif
	int poll_ms;
#ifdef OCT8TOR
	int oct_nr;
	int oct_azim, oct_elev, oct_stop;
	bool oct_hidden;
	char oct_sys;
#endif
    GThread *main_thread;
};


extern GPtrArray *rotars;
extern MUTEX_DEFINE(rotars);
extern struct rotar *rotar;
extern struct oct8tor *goct8tor;


int init_rotars(void);
int free_rotars(void);

struct rotar *init_rotar(struct config_rotar *cfg, int rotchar);
void free_rotar(struct rotar *rot);
int rot_seek(struct rotar *rot, int uhel, int elev /* -90 unused */);
void rotars_stop(void);
void rotar_stop(struct rotar *rot);
struct config_rig *get_config_rig_by_number(GPtrArray *crigs, int nr);
struct config_rotar *get_config_rotar_by_number(GPtrArray *rotars, int nr);
struct rotar *get_rotar(int nr);
struct rotar *get_rotar_by_rotstr(char *rotstr);
void rotar_read_handler(int n, char **line);
void timer_update_rotar(void *arg);
void rotar_remote_update(char *c);
void menu_rotar(void *arg);

#ifdef Z_HAVE_SDL
int rot_update_colors(void);
#endif

int rotar_main(struct sdev *sdev);
int rot_beamwidth(void);
gpointer rot_hamlib_main(gpointer xxx);

int rot_normalize(int az);

char rot_get_rotchar_by_oct_nr(int oct_nr);
char rot_get_rotchar_by_ch(const char *ch);
char rot_get_rotchar_by_sys(const char *sys);

#endif
