/*
 *
 * Copyright (c) Vaisala Group 2009. All rights reserved.
 *
 * The terms "Vaisala" and "Vaisala Group" are defined as
 * "Vaisala Oyj and all its subsidiaries".
 *
 */

/** @file radar_sweep.h
 *  API of the radar sweep data container.
 */

#ifndef RADAR_SWEEP_H
#define RADAR_SWEEP_H

#ifdef __cplusplus
extern "C" {
#endif

/** @defgroup gr_radar_sweep Radar Sweep Data Container
 * 
 * A sweep is a collection of rays grouped together by scanning
 * scheduler. Most common types of sweeps are a fixed elevation sweep
 * (PPI) and a fixed azimus sweep (RHI).
 *  
 *  @ingroup gr_polar_data
 *  @{
 */

/** @defgroup gr_radar_sweep_conf Radar Sweep Configuration
 *
 *  Configuration shared by all or a subset of sweeps. It encompases
 *  almost all sweep metadata with the exception of properties like
 *  the time and the fixed angle, which are unique for each sweep.
 *
 * @ingroup gr_radar_sweep
 * @{
 */

enum sweep_type {
    UNKNOWN_SWEEP,
    PPI_SWEEP,     /**< Constant Elevation Sweep */
    RHI_SWEEP,     /**< Constant Azimuth Sweep */
    MANUAL_SWEEP   /**< */
};

/* Forward declarations */
struct radar_sweep_conf;

struct radar_sweep_conf * sweepconf_new_manual(void);

struct radar_sweep_conf *
sweepconf_new_ppi(const struct dscan * start_step_count);

struct radar_sweep_conf *
sweepconf_new_rhi(const struct dscan * start_step_count);

/** Compare two configurations. Returns 0 if different, 1 if identical */
int sweepconf_compare(struct radar_sweep_conf * sc1,
                      struct radar_sweep_conf * sc2);

/** Iterator for ray configuration. If "rconf" is NULL, it returns first
    configuration. If "rconf" is the last config, it returns NULL */
struct radar_ray_conf *
sweepconf_get_next_rayconf(const struct radar_sweep_conf * sconf,
                           struct radar_ray_conf * rconf);

/** Add ray configuration. Returns pointer to the newly added
    configuration or existing equivalent. */
struct radar_ray_conf *
sweepconf_add_rayconf(struct radar_sweep_conf * sconf,
                      struct radar_ray_conf * rconf);

/** Get number of number of shared ray configurations in the sweep config. */
int sweepconf_get_rayconf_count(const struct radar_sweep_conf * sconf);


enum sweep_type sweepconf_get_type(const struct radar_sweep_conf * sc);

/** Get starting angle, step, and number of steps (see dscan on radar_ray.h) */
struct dscan * sweepconf_get_sector(const struct radar_sweep_conf * sc,
                                    struct dscan * buf);

int sweepconf_add_int(struct radar_sweep_conf * sc,
                      const char * name, int val);
int sweepconf_add_u64(struct radar_sweep_conf * sc,
                      const char * name, uint64_t val);
int sweepconf_add_double(struct radar_sweep_conf * sc,
                         const char * name, double val);
int sweepconf_add_string(struct radar_sweep_conf * sc,
                         const char * name, const char * val);
int sweepconf_add_buf(struct radar_sweep_conf * sconf,
                      const char * name, const void * buf, size_t len);

int sweepconf_is_defined(const struct radar_sweep_conf * sc,
                         const char * name);
int sweepconf_get_int(const struct radar_sweep_conf * sc,
                      const char * name);
uint64_t sweepconf_get_u64(const struct radar_sweep_conf * sc,
                           const char * name);
double sweepconf_get_double(const struct radar_sweep_conf * sc,
                            const char * name);
char * sweepconf_get_string(const struct radar_sweep_conf * sc,
                                const char * name, char * buf, size_t len);
char * sweepconf_get_buf(const struct radar_sweep_conf * sconf,
                         const char * name, void * buf, size_t * len);

struct radar_sweep_conf * sweepconf_from_node(struct dllist_node * node);
struct dllist_node * sweepconf_get_node(struct radar_sweep_conf * sc);

/** Aquire reference to radar sweep configuration, return NULL if failed */
struct radar_sweep_conf * sweepconf_ref(struct radar_sweep_conf * sc);

/** Drop reference to radar sweep configuraton, delete on last dereference */
void sweepconf_unref(struct radar_sweep_conf * sc);

/** @}  gr_radar_sweep */

/* =================== */

struct radar_sweep;

struct radar_sweep * rsweep_new(struct radar_sweep_conf * sconf);

struct radar_sweep * rsweep_new_copy(struct radar_sweep * sweep);
void rsweep_delete(struct radar_sweep * sweep);

struct radar_sweep * rsweep_from_node(struct dllist_node * node);
struct dllist_node * rsweep_get_node(struct radar_sweep * sweep);

const struct radar_scan * rsweep_get_my_scan(const struct radar_sweep * sweep);
int rsweep_set_my_scan(struct radar_sweep * sweep,
                       const struct radar_scan * scan);

struct timeval * rsweep_get_starttime(const struct radar_sweep * sweep,
                                      struct timeval * tv);

struct timeval * rsweep_get_stoptime(const struct radar_sweep * sweep,
                                     struct timeval * tv);

struct timeval * rsweep_get_time(const struct radar_sweep * sweep,
                                 struct timeval * tv);

int rsweep_set_time(struct radar_sweep * sweep, const struct timeval * tv);

double rsweep_get_fixed_angle(const struct radar_sweep* sweep);

int rsweep_set_fixed_angle(struct radar_sweep* sweep, double fixed_angle);

/** Get the first valid ray in the sweep.  Returns NULL if there are none */
struct radar_ray * rsweep_get_first_ray(const struct radar_sweep * sweep);

/** Get a ray from the sweep by index. If the index is invalid, or the ray
    is missing, it returns NULL */
struct radar_ray * rsweep_get_ray(const struct radar_sweep * sweep, int index);


/** Add ray to the list of this sweep rays. Returns index of the new ray. */
int rsweep_add_ray(struct radar_sweep * sweep,
                   struct radar_ray * ray);

/** Get actual number of rays in the sweep. It may be different from
    the intended(configured) number of rays */
int rsweep_get_ray_count(const struct radar_sweep* sweep);

/** Get index of the first recorded ray, a1gate in ODIM */ 
int rsweep_get_earliest_ray(const struct radar_sweep* sweep);

/** Get index of the sweep in the volume scan schedule. Some indexes
 * might be missing */
int rsweep_get_schedule_index(const struct radar_sweep* sweep);

/** Set index/position of the sweep in the volume scan schedule.  */
int rsweep_set_schedule_index(struct radar_sweep* sweep, int index);

/** Replace all occurence of "old" with "new" ray configuration. All rays
    refering to "old" will be updated to point to "new" */
struct radar_ray_conf * rsweep_swap_rayconf(struct radar_sweep * sweep,
                                            struct radar_ray_conf * new_conf,
                                            struct radar_ray_conf * old_conf);

/** Get pointer to this sweep config */
struct radar_sweep_conf * rsweep_get_config(struct radar_sweep * sweep);

/** If config is "old", replace it with "new" sweep configuration. Returns effective
 configuration, which is "new" is swap was succeseful. Discarded config is
 automatically dereferenced, just as new one is automatically referenced. */
struct radar_sweep_conf * rsweep_swap_config(struct radar_sweep * sweep,
                                             struct radar_sweep_conf * new_conf,
                                             struct radar_sweep_conf * old_conf);


    struct radar_position * rsweep_get_position(const struct radar_sweep * rsweep);

double rsweep_get_sweep_speed(const struct radar_sweep* sweep);
double rsweep_get_beam_widthH(const struct radar_sweep* sweep);
double rsweep_get_beam_widthV(const struct radar_sweep* sweep);

/** @}  gr_radar_sweep */

#ifdef __cplusplus
}
#endif
#endif /* RADAR_SWEEP_H */
