// ==================================================================== //
//                                                                      //
//   File      : ad_config.h                                            //
//   Purpose   : Read/write editor configurations                       //
//                                                                      //
//                                                                      //
// Coded by Ralf Westram (coder@reallysoft.de) in May 2005              //
// Copyright Department of Microbiology (Technical University Munich)   //
//                                                                      //
// Visit our web site at: http://www.arb-home.de/                       //
//                                                                      //
// ==================================================================== //

#ifndef AD_CONFIG_H
#define AD_CONFIG_H

#ifndef ARBDB_BASE_H
#include "arbdb_base.h"
#endif
#ifndef ARBTOOLS_H
#include <arbtools.h>
#endif
#ifndef ARB_STRBUF_H
#include <arb_strbuf.h>
#endif

#define CONFIG_DATA_PATH "configuration_data"
#define CONFIG_ITEM      "configuration"

#define DEFAULT_CONFIGURATION "default_configuration"

GBDATA *GBT_find_configuration(GBDATA *gb_main, const char *name);
void    GBT_get_configuration_names(struct ConstStrArray& configNames, GBDATA *gb_main);

class GBT_config : virtual Noncopyable {
    char *top_area;
    char *middle_area;
    char *comment; // NULp if no comment exists
public:
    GBT_config(GBDATA *gb_main, const char *name, GB_ERROR& error);
    GBT_config() : top_area(NULp), middle_area(NULp), comment(NULp) {}
    ~GBT_config() {
        free(top_area);
        free(middle_area);
        free(comment);
    }

    static const int TOP_AREA    = 0;
    static const int MIDDLE_AREA = 1;

    bool exists() const { return top_area || middle_area; }

    const char *get_definition(int area) const {
        arb_assert(area == TOP_AREA || area == MIDDLE_AREA);
        return area == TOP_AREA ? top_area : middle_area;
    }
    void set_definition(int area, char *new_def) {
        arb_assert(area == TOP_AREA || area == MIDDLE_AREA);
        char*& Area = area == TOP_AREA ? top_area : middle_area;
        freeset(Area, new_def);
    }

    const char *get_comment() const { return comment; }
    void set_comment(const char *newComment) { freedup(comment, newComment); }

    GB_ERROR saveAsOver(GBDATA *gb_main, const char *name, const char *oldName, bool warnIfSavingDefault) const;
    GB_ERROR save(GBDATA *gb_main, const char *name, bool warnIfSavingDefault) const {
        return saveAsOver(gb_main, name, name, warnIfSavingDefault);
    }
};

enum GBT_CONFIG_ITEM_TYPE {
    CI_UNKNOWN       = 1,
    CI_GROUP         = 2,
    CI_FOLDED_GROUP  = 4,
    CI_SPECIES       = 8,
    CI_SAI           = 16,
    CI_CLOSE_GROUP   = 32,
    CI_END_OF_CONFIG = 64,
};

struct GBT_config_item : virtual Noncopyable {
    GBT_CONFIG_ITEM_TYPE  type;
    char                 *name;

    GBT_config_item() : type(CI_UNKNOWN), name(NULp) {}
    GBT_config_item(GBT_CONFIG_ITEM_TYPE type_, const char *name_) : type(type_), name(nulldup(name_)) {}
    ~GBT_config_item() { free(name); }

    void append_to_config_string(GBS_strstruct& out) const;
};

class GBT_config_parser : virtual Noncopyable {
    char *config_string;
    int   parse_pos;

    GBT_config_item item;
public:
    GBT_config_parser(const GBT_config& cfg, int area)
        : config_string(nulldup(cfg.get_definition(area))),
          parse_pos(0)
    {}
    ~GBT_config_parser() { free(config_string); }

    const GBT_config_item& nextItem(GB_ERROR& error);
};

#if defined(DEBUG)
void GBT_test_config_parser(GBDATA *gb_main);
#endif // DEBUG

#else
#error ad_config.h included twice
#endif // AD_CONFIG_H

