/*
===========================================================================
Copyright (C) 2015 the OpenMoHAA team

This file is part of OpenMoHAA source code.

OpenMoHAA source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.

OpenMoHAA source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with OpenMoHAA source code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
===========================================================================
*/

// configurator.h: Config class for INI files.

#ifndef __CONFIGURATOR_H__
#define __CONFIGURATOR_H__

#include <listener.h>

#define MAX_CONFIGURATOR_ARRAY_SIZE 2048

typedef struct configValue_s {
    bool m_bNeedWrite;
    str  value;
} configValue_t;

typedef struct configKey_s {
    bool                     m_bNeedWrite;
    str                      name;
    Container<configValue_t> value;
    bool                     m_bArray;
} configKey_t;

typedef struct configSection_s {
    bool                     m_bNeedWrite;
    str                      name;
    Container<configKey_t *> key;
} configSection_t;

enum {
    LINE_EMPTY,
    LINE_COMMENT,
    LINE_SECTION,
    LINE_VALUE,
    LINE_ERROR
};

class Configurator : public Class
{
private:
    str  m_filename;
    bool m_bNoWrite;
    bool m_bNeedWrite;

    con_set<str, configSection_t> m_sections;
    Container<configSection_t *>  m_reverseSections;

private:
    size_t       GetLine(char *dest, const char *data, size_t size);
    str          GetValue(const char *section, const char *key, str defaultValue, int index = -1);
    configKey_t *GetKey(const char *section, const char *key, int index = -1);

    int  CutLine(char *data);
    bool SetupLine(char *line, int& lineno, size_t& len, size_t& last);
    bool FindData(int type, const char *section, const char *key, size_t *offset, const char *data, size_t size);
    void ParseData(const char *data, size_t size);
    void WriteData(char **data, size_t *size);
    void WriteData2(char **data, size_t *size);
    int  ParseLine(char *line, char *section, char *key, char *value);

    configSection_t *CreateSection(const char *section);
    configSection_t *FindSection(const char *section);
    int              GetKeyArray(char *key);
    int              GetKeyArray(str& key);
    configKey_t     *CreateKey(configSection_t *section, const char *key, unsigned int *index);
    configKey_t     *FindKey(configSection_t *section, const char *key);
    void             RemoveSection(configSection_t *section);
    void             RemoveKey(configSection_t *section, configKey_t *key);

public:
    CLASS_PROTOTYPE(Configurator);

    Configurator(const char *filename);
    Configurator();
    ~Configurator();

    void Parse(const char *filename);
    void Close();
    void SetWrite(bool bWrite);

    str   GetString(const char *section, const char *key, str defaultValue, int index = -1);
    int   GetInteger(const char *section, const char *key, int defaultValue, int index = -1);
    float GetFloat(const char *section, const char *key, float defaultValue, int index = -1);
    void  SetString(const char *section, const char *key, str value, int index = -1);
    void  SetInteger(const char *section, const char *key, int value, int index = -1);
    void  SetFloat(const char *section, const char *key, float value, int index = -1);
};

void test_config(void);

#endif /* __CONFIGURATOR_H__ */
