#ifndef CLASSIFIER_H
#define CLASSIFIER_H

#include "freesasa_internal.h"

/**
    This classifier only has the sasa_class() and class2str()
    functions, which returns 1 for protein backbone atoms, and 0
    else. Backbone atoms are CA, N, C and O.
 */
extern const freesasa_classifier freesasa_backbone_classifier;

//! Classifier that classifies each atom according to residue
extern const freesasa_classifier freesasa_residue_classifier;


/**
    The following three structs and the following functions are only
    exposed in a header because the autogenerated static classifiers
    need to see them, they are not intended for use outside of this
    context. Therefore the functions to modify the structs are hidden
    inside classifier.c.

    Names of classes, types, etc are stored in arrays to simplify
    generic searching.
*/

/**
    Struct to store information about the types-section in a user-config.
 */
struct classifier_types {
    int n_types; //!< number of types
    char **name; //!< names of types
    double *type_radius; //!< radius of type
    freesasa_atom_class *type_class; //!< class of each type
};


/**
     Configuration info for each residue type.
 */
struct classifier_residue {
    int n_atoms; //!< Number of atoms
    char *name; //!< Name of residue
    char **atom_name; //!< Names of atoms
    double *atom_radius; //!< Atomic radii
    freesasa_atom_class *atom_class; //!< Classes of atoms
    freesasa_nodearea max_area; //!< Maximum area (for RSA)
};

/**
    Stores a user-configuration as extracted from a configuration
    file. No info about types, since those are only a tool used
    intermediately in assigment of radii and classes.
    
    An array of the names of residues is stored directly in the struct
    to facilitate searching for residues. The class_name array should
    be a clone of that found in struct types (can be done bye
    config_copy_classes()).

    Only for internal use.
 */
struct freesasa_classifier {
    int n_residues; //!< Number of residues
    char **residue_name; //!< Names of residues
    char *name;
    struct classifier_residue **residue;
};

/**
    Get the VdW radius of an element
 */
double
freesasa_guess_radius(const char* symbol);

const freesasa_nodearea *
freesasa_classifier_residue_reference(const freesasa_classifier *classifier,
                                      const char *res_name);

// The functions below are only exposed to allow testing
freesasa_classifier* 
freesasa_classifier_new();

struct classifier_types*
freesasa_classifier_types_new();

void
freesasa_classifier_types_free(struct classifier_types* t);

struct classifier_residue*
freesasa_classifier_residue_new(const char* name);

void
freesasa_classifier_residue_free(struct classifier_residue* res);

int
freesasa_classifier_add_residue(struct freesasa_classifier *c,
                                const char* name);

int
freesasa_classifier_add_atom(struct classifier_residue *res,
                             const char *name,
                             double radius,
                             int the_class);

int
freesasa_classifier_add_type(struct classifier_types *types,
                             const char *type_name,
                             const char *class_name, 
                             double r);

int
freesasa_classifier_add_class(struct classifier_types *types,
                              const char *name);


// These three are used to calculate residue type areas

int
freesasa_classify_n_residue_types();

int
freesasa_classify_residue(const char *res_name);

const char *
freesasa_classify_residue_name(int residue_type);

#endif /* CLASSIFIER_H */
