/*
 * Pspell interface header file
 * Copyright 2000 by Kevin Atkinson under the terms of the LGPL
 *
 */

#ifndef PSPELL_CONFIG__H
#define PSPELL_CONFIG__H

#include "error.h"
#include "string_emulation.h"
#include "string_pair_emulation.h"
#include "mutable_container.h"

enum PspellKeyInfoType {PspellKeyInfoString, 
			PspellKeyInfoInt, 
			PspellKeyInfoBool,
			PspellKeyInfoList}; 

#ifndef __cplusplus
  typedef enum PspellKeyInfoType PspellKeyInfoType;
#endif

struct PspellKeyInfo { 
  /* 
   * The KeyInfo object is used for holding infomation about a valid
   * key 
   */

  const char *       name;  /* the name of the key                      */
  PspellKeyInfoType  type;  /* the key type                             */
  const char * def;         /* the default value of the key             */
  const char * desc;        /* a brief description of the key or        *
                             * null if internal value                   */
  char otherdata[16];       /* other data used by config implementation *
                             * should be set to 0 if not used           */
};

#ifndef __cplusplus 

typedef struct PspellKeyInfo          PspellKeyInfo;

#endif

#ifdef __cplusplus 
 
  class PspellKeyInfoEmulation {
  public:
    virtual PspellKeyInfoEmulation * clone() const = 0;
    virtual void assign(const PspellKeyInfoEmulation *) = 0;
    virtual bool at_end() const = 0;
    virtual const PspellKeyInfo * next() = 0;
    virtual ~PspellKeyInfoEmulation() {}
  };

#else

  typedef struct PspellKeyInfoEmulation PspellKeyInfoEmulation;

#endif

#ifndef __cplusplus
  typedef struct PspellConfig PspellConfig;
#else
  class PspellConfig;
#endif

#ifdef __cplusplus
extern "C" {
#endif

  /* Note: The string that is returned by functions that use the
   *       temporary string are only valid until the next function is
   *       called that uses a temporary string.  Not all functions
   *       that use the temporary string necessarily return a string
   */

  PspellConfig * new_pspell_config();

  void delete_pspell_config(PspellConfig *);
  
  int pspell_config_error_number(const PspellConfig *);
  
  const char * pspell_config_error_message(const PspellConfig *);

  const PspellErrorExtraInfo * 
    pspell_config_error_extra_info(const PspellConfig *);


  PspellConfig * pspell_config_clone(PspellConfig *);
  /* returns a new copy of itself or null if its not copyable
   * will set error_num to PERROR_CANT_COPY if it returns null
   */
  
  int pspell_config_assign(PspellConfig *, const PspellConfig * other);
  /* assign other to this.
   * returns false and sets error_num to PERROR_CANT_COPY if the object
   * is not copyable                                                 
   */

  void pspell_config_set_extra(PspellConfig *,
			       const PspellKeyInfo * begin, 
			       const PspellKeyInfo * end);
  /* sets extra keys which this config class should accept
   * begin and end are expected to point to the begging and end of
   * an array of PspellKeyInfos.
   */

  const PspellKeyInfo * pspell_config_keyinfo(PspellConfig *, 
					      const char * key);
  /* returns the KeyInfo object for the corresponding key or 
   * returns null and sets error_num to PERROR_UNKNOWN_KEY 
   * if the key is not valid
   * The pointer returned is valid for the lifetime of the object.
   */

  PspellKeyInfoEmulation * 
  pspell_config_possible_elements(PspellConfig *, int include_extra);
  /* returns a newly allocated emulation of all the possible objects
   * this config class uses
   */

  const char * pspell_config_get_default(PspellConfig *, const char * key);
  /* returns the default value for given key which way involve
   * substating variables, thus it is not the same as keyinfo(key)->def
   * returns null and sets error_num to PERROR_UNKNOWN_KEY if the key
   * is not valid.
   * Uses the temporary string.
   */

  PspellStringPairEmulation * pspell_config_elements(PspellConfig *);
  /* returns a newly alloacted emulation of all the key/value pairs.
   * This DOES not include ones which are set to their default values
   */

  int pspell_config_replace(PspellConfig *,
			     const char * key, const char * value);
  /* inserts an item, if the item already exists it will be replaced.
   * returns true if it succesed or false on error
   * if the key in not valid         sets error_num to PERROR_UNKNOWN_KEY
   * if the value is not valid       sets error_num to PERROR_BAD_VALUE
   * if the value can not be changed sets error_num to PERROR_CANT_CHANGE_VALUE
   * if the value is a list and you are trying to set it directory
   *                                 sets error_num to PERROR_LIST_SET
   */

  int pspell_config_remove(PspellConfig *, const char * key);
  /* remove a key and returns true if it exists otherise return false
   * This effictly sets the key to its default value.
   * calling replace with a value of "<default>" will also call remove
   * if the key does not exists      sets error_num to 0 or PERROR_NOT
   * if the key in not valid         sets error_num to PERROR_UNKNOWN_KEY
   * if the value can not be changed sets error_num to PERROR_CANT_CHANGE_VALUE
   */
  
  int pspell_config_have(const PspellConfig *, const char *);
  /* all of the retrive methods use the use the temporary string
   * and may set error_num to PERROR_UNKNOWN_KEY
   */

  const char * pspell_config_retrieve (PspellConfig *, const char * key);
  /* returns null on error */

  int pspell_config_retrieve_list (PspellConfig *, const char * key, 
				   PspellMutableContainer *);

  int pspell_config_retrieve_bool(PspellConfig *, const char * key);
  /* return -1 on error, 0 if false, 1 if true */

  int pspell_config_retrieve_int(PspellConfig *, const char * key);
  /* return -1 on error */

#ifdef __cplusplus
}
#endif

#ifdef __cplusplus
class PspellConfig : public PspellCanHaveError {

 public:
  
  virtual PspellConfig * clone() = 0;

  virtual bool assign(const PspellConfig * other) = 0;

  virtual void set_extra(const PspellKeyInfo * begin, 
			 const PspellKeyInfo * end) = 0;

  virtual const PspellKeyInfo * keyinfo(const char * key) = 0;

  virtual PspellKeyInfoEmulation * possible_elements(bool include_extra) = 0;
  PspellKeyInfoEmulation * possible_elements() 
    {return possible_elements(true);}

  virtual const char * get_default(const char * key) = 0;

  virtual PspellStringPairEmulation * elements() = 0;

  virtual bool replace(const char * key, const char * value) = 0;

  virtual bool remove(const char * key) = 0;
   
  virtual bool have (const char *) const = 0;

  virtual const char * retrieve (const char * key) = 0;

  virtual bool retrieve_list (const char * key, 
			      PspellMutableContainer &) = 0;

  virtual int retrieve_bool(const char * key) = 0;

  virtual int retrieve_int(const char * key) = 0;

  virtual ~PspellConfig() {}
};
#endif

#endif /* PSPELL_CONFIG__H */
