//  ==================================================================== //
//                                                                       //
//    File      : config_manager.hxx                                     //
//    Purpose   : general interface to store/restore                     //
//                a set of related awars                                 //
//                                                                       //
//  Coded by Ralf Westram (coder@reallysoft.de) in January 2002          //
//  Copyright Department of Microbiology (Technical University Munich)   //
//                                                                       //
//  Visit our web site at: http://www.arb-home.de/                       //
//                                                                       //
//  ==================================================================== //

#ifndef CONFIG_MANAGER_HXX
#define CONFIG_MANAGER_HXX

#ifndef CONFIGMAPPING_H
#include <ConfigMapping.h>
#endif
#ifndef AW_BASE_HXX
#include <aw_base.hxx>
#endif
#ifndef CB_H
#include <cb.h>
#endif

#define awt_assert(cond) arb_assert(cond)

struct ConfigMapping;
class  AWT_config_definition;

struct AWT_config_mapping_def {
    const char *awar_name;
    const char *config_name; // Note: this key defines the write-order during 'restore'; see also config_manager.cxx@write_to_awars
};

struct AWT_predefined_config {
    const char *name;        // of predefined config (has to begin with '*')
    const char *description;
    const char *config;      // config string (as generated by AWT_config::config_string)
};

// -------------------
//      AWT_config

class AWT_config : virtual Noncopyable {
    // stores one specific configuration (key->value pairs)
    //
    // this class allows to modify the config_string before calling AWT_config_definition::write().
    // This is e.g. necessary if some config-entries change and you want to support
    // automatic conversion from old format to new format.

    ConfigMapping *mapping;
    GB_ERROR       parse_error;     // set by AWT_config(const char *)

    void init_from_awars(const ConfigMapping& cfgname2awar);

public:
    AWT_config(const char *cfgStr);
    AWT_config(const ConfigMapping& cfgname2awar);        // internal use (reads current awar values)
    AWT_config(const AWT_config_definition *cfg_def);     // internal use (reads current awar values)
    ~AWT_config();

    GB_ERROR parseError() const { return parse_error; }

    // props + modifiers
    bool has_entry(const char *entry) const {
        // returns true if mapping contains 'entry'
        awt_assert(!parse_error);
        return mapping->has_entry(entry);
    }
    const char *get_entry(const char *entry) const {
        // returns value of 'entry'
        awt_assert(!parse_error);
        return mapping->get_entry(entry);
    }
    void set_entry(const char *entry, const char *value) {
        // sets a (new) entry to value
        awt_assert(!parse_error);
        mapping->set_entry(entry, value);
    }
    void delete_entry(const char *entry) {
        // deletes an existing 'entry'
        awt_assert(!parse_error);
        mapping->delete_entry(entry);
    }


    // result
    char *config_string() const { // @@@ change result type to string?
        // return current state as config string
        awt_assert(!parse_error);
        return ARB_strdup(mapping->config_string().c_str());
    }
    void get_entries(class ConstStrArray& to_array);

    void write_to_awars(const ConfigMapping& cfgname2awar, bool warn) const; // internal use (write config into awars)
};

// ------------------------------
//      AWT_config_definition

class AWT_config_definition : virtual Noncopyable {
    ConfigMapping *config_mapping; // defines config-name -> awar-name relation

public:
    AWT_config_definition();
    AWT_config_definition(AWT_config_mapping_def *mapping_definition); // simple definition
    ~AWT_config_definition();

    void add(const char *awar_name, const char *config_name);
    void add(const char *awar_name, const char *config_name, int counter);
    void add(const AWT_config_mapping_def *mapping_definition);

    char *read() const;                   // awars -> config string (heap copy)
    void write(const char *cfgStr) const; // config string -> awars (use to restore a saved configuration)
    void reset() const;                   // reset awars to defaults

    const ConfigMapping& get_mapping() const { awt_assert(config_mapping); return *config_mapping; }
};

// ----------------------------------------
//      callbacks from config manager :

DECLARE_CBTYPE_FVV_AND_BUILDERS(ConfigSetupCallback,   void, AWT_config_definition&); // defines makeConfigSetupCallback
DECLARE_CBTYPE_VV_AND_BUILDERS (StoreConfigCallback,   char*);                        // defines makeStoreConfigCallback
DECLARE_CBTYPE_FVV_AND_BUILDERS(RestoreConfigCallback, void, const char *);           // defines makeRestoreConfigCallback

// ----------------------------------
// the config manager itself
// adds button at cursor position when called (from a window generator function)

void AWT_insert_config_manager(AW_window *aww, AW_default default_file_, const char *id, const StoreConfigCallback& store, const RestoreConfigCallback& load_or_reset, const char *macro_id = NULp, const AWT_predefined_config *predef = NULp);
void AWT_insert_config_manager(AW_window *aww, AW_default default_file_, const char *id, ConfigSetupCallback setup_cb,                                                 const char *macro_id = NULp, const AWT_predefined_config *predef = NULp);
void AWT_insert_config_manager(AW_window *aww, AW_default default_file_, const char *id, const AWT_config_mapping_def *mapping,                                        const char *macro_id = NULp, const AWT_predefined_config *predef = NULp);

// the following methods provide support to configure special use-cases of AWT_insert_config_manager:
void AWT_define_config_manager_conversion(const char *old_config_id, const char *new_config_id, const char *name_prefix = NULp);
void AWT_predef_config_manager(const char *macro_id, const char *window_title);

// -------------------------------
//      modify stored configs

typedef char *(*ConfigModifyCallback)(const char *key, const char *value, AW_CL cl_user);
void AWT_modify_managed_configs(AW_default default_file_, const char *id, ConfigModifyCallback mod_cb, AW_CL cl_user);

#else
#error config_manager.hxx included twice
#endif // CONFIG_MANAGER_HXX

