/*
 * storedconfig.h
 *
 * A very stupid and minimalistic application configuration stored somewhere on the target
 */

#ifndef STOREDCONFIG_H_
#define STOREDCONFIG_H_

#include <stdint.h>

class StoredConfig
{
public:

    enum
    {
        k_max_binary_size=256*1024, //Warning: real available size depend on target (only 100K on DSP)
        k_max_app_config_size=4*1024,
    };

    enum type_t
    {
    	type_raw=0,
    	type_int=1,
    	type_uint=2,
    	type_float=3
    };

    static StoredConfig& instance();

    static bool loaded();

    void initialize();

    void disable(bool dis=true);

    //int getenv_raw_typed(const char* name, void* value, const void* default_value, type_t* t=0);  //Warning: sizeof(value) shall be at least 4 bytes
    //void setenv_raw_typed(const char* name, void* value, type_t t=type_raw);
    //void setenv_raw_typed(int index, void* value, type_t t=type_raw);

    int getenv_raw(const char* name, void* value, const void* default_value);  //Warning: sizeof(value) shall be at least 4 bytes
    void setenv_raw(const char* name, void* value);
    void setenv_raw(int index, void* value);

    void clearenv_raw(const char* name);
    void clearenv_raw(int n);
    void clearenv_all();

    void save_env();	//warning: env vars are not stored byt setenv, but only by an explicit save to preserve NRM writes

    template<typename T_> bool get_env(const char* name, T_& value) //warning use only type representable with an unsigned long
    {
    	return getenv_raw(name, &value, 0)>0;
    }
    template<typename T_> bool get_env(const char* name, T_& value, T_ default_value) //warning use only type representable with an unsigned long
    {
    	T_ def_value=default_value;
    	return getenv_raw(name, &value, &def_value)>0;
    }

    template<typename T_> T_ get_env_default(const char* name, T_ default_value) //warning use only type representable with an unsigned long
    {
    	T_ value=0;
    	bool ok=get_env(name, value, default_value);
    	if (!ok)
    		return default_value;
    	return value;
    }

    template<typename T_> void set_env(const char* name, T_ value) //warning use only type representable with an unsigned long
    {
    	T_ x=value;
    	setenv_raw(name, &x);
    }

    void invokeStartupScript(bool exec_if_it_is_invalid=false) const;

    template<typename T_> bool loadAppConfig(T_ * cfg, unsigned int version_id) const
    {
    	return loadRawAppConfig(cfg, sizeof *cfg, version_id);
    }

    template<typename T_> bool saveAppConfig(const T_ * cfg, unsigned int version_id)
    {
    	return saveRawAppConfig(cfg, sizeof *cfg, version_id);
    }

    bool loadRawAppConfig(void* raw, unsigned int size, unsigned int version_id) const;
    bool saveRawAppConfig(const void* raw, unsigned int size, unsigned int version_id);

    bool loadRawBinaryData(void* destination, unsigned int size, unsigned int version_id, unsigned int offset=0) const;
    bool saveRawBinaryData(const void* source, unsigned int size, unsigned int version_id, unsigned int offset=0);

    bool saveRawBinaryDataAsynch(const void* source, unsigned int size, unsigned int version_id, unsigned int offset=0);

    bool pendingAsynchSave();

    template<typename T_> bool loadBinaryData(T_ * dst , unsigned int version_id, unsigned int offset=0) const
    {
    	return loadRawBinaryData(dst, sizeof(T_), version_id, offset);
    }

    template<typename T_> bool saveBinaryData(const T_ * src, unsigned int version_id, unsigned int offset=0)
    {
    	return saveRawBinaryData(src, sizeof *src, version_id, offset);
    }

    template<typename T_> bool saveBinaryDataAsynch(const T_ * src, unsigned int version_id, unsigned int offset=0)
    {
    	return saveRawBinaryDataAsynch(src, sizeof *src, version_id, offset);
    }

    bool binaryDataTest(unsigned int offset=0);	//Warning destructive!!

    struct timestamp_str_t
    {
    	unsigned int day: 5;
    	unsigned int month: 4;
    	unsigned int year: 6;	//2000+year -> from 2000 up to 2063
    	unsigned int hours: 5;
    	unsigned int minutes: 6;
    	unsigned int seconds: 6;
    };
    union timestamp_t
    {
    	timestamp_str_t str;
    	unsigned int raw;
    };

    void historySetTimestamp(timestamp_t ts);//void historySetTimestamp(const char* fmt, ...);
    void historyClear();

    void historyStart(unsigned int id, const char* msg, const char* msg1=0);

    void historySave(char htype, const char* hname, const void* data, unsigned int data_size, const char* msg, ...);

    void historySaveExt(char htype, const char* hname, const char* decoder_name, unsigned int decoder_id, const void* data, unsigned int data_size, const char* msg, ...);

    void historyFlush();
private:
    StoredConfig();

    StoredConfig(const StoredConfig&);
    void operator=(const StoredConfig&);
};


#endif /* STOREDCONFIG_H_ */
