// ============================================================ //
//                                                              //
//   File      : awti_imp_local.hxx                             //
//   Purpose   : local definitions for import                   //
//                                                              //
//   Institute of Microbiology (Technical University Munich)    //
//   www.arb-home.de                                            //
//                                                              //
// ============================================================ //

#ifndef AWTI_IMP_LOCAL_HXX
#define AWTI_IMP_LOCAL_HXX

#ifndef _GLIBCXX_STRING
#include <string>
#endif

#ifndef ARBDBT_H
#include <arbdbt.h>
#endif
#ifndef AWTI_IMPORT_HXX
#include <awti_import.hxx>
#endif
#ifndef ARB_STRARRAY_H
#include <arb_strarray.h>
#endif
#ifndef XFERSET_H
#include <xferset.h>
#endif
#ifndef XFERGUI_H
#include <xfergui.h>
#endif

#define awti_assert(cond) arb_assert(cond)

// more awars defined at awti_import.hxx@AWAR_IMPORT
#define AWAR_IMPORT_FILEBASE AWAR_IMPORT_TMP_PREFIX "pattern"
#define AWAR_IMPORT_FILENAME AWAR_IMPORT_FILEBASE "/file_name"

#define AWAR_IMPORT_FORMATBASE   AWAR_IMPORT_TMP_PREFIX "form"
#define AWAR_IMPORT_FORMATNAME   AWAR_IMPORT_FORMATBASE "/file_name"
#define AWAR_IMPORT_FORMATFILTER AWAR_IMPORT_FORMATBASE "/filter"
#define AWAR_IMPORT_FORMATDIR    AWAR_IMPORT_FORMATBASE "/directory"

#define AWAR_IMPORT_FORMAT_DESC    AWAR_IMPORT_TMP_PREFIX "description"
#define AWAR_IMPORT_ALI            AWAR_IMPORT_TMP_PREFIX "alignment"
#define AWAR_IMPORT_ALI_TYPE       AWAR_IMPORT_TMP_PREFIX "alignment_type"
#define AWAR_IMPORT_ALI_PROTECTION AWAR_IMPORT_TMP_PREFIX "alignment_protection"

#define AWAR_IMPORT_FTS AWAR_IMPORT_TMP_PREFIX "fts"

#define AWTI_IMPORT_CHECK_BUFFER_SIZE 10000


struct import_match : virtual Noncopyable {
    // one for each "MATCH" section of the import format

    char *match;

    // variables get expanded when one of the following variables is used:
    // (search for 'expandSetVariables')
    char *aci;
    char *srt;
    char *mtag;
    char *append;
    char *write;
    // --------------------

    char     *setvar;
    GB_TYPES  type;
    char     *defined_at; // where was match defined

    import_match *next;

    import_match *reverse(import_match *to_append) {
        import_match *rest = next;
        next = to_append;
        return rest ? rest->reverse(this) : this;
    }

    import_match();
    ~import_match();
};

#define IFS_VARIABLES 26                            // 'a'-'z'

class SetVariables {
    typedef SmartPtr<std::string> StringPtr;
    StringPtr value[IFS_VARIABLES];

public:
    SetVariables() {}

    void set(char c, const char *s) {
        awti_assert(c >= 'a' && c <= 'z');
        value[c-'a'] = new std::string(s);
    }
    const std::string *get(char c) const {
        awti_assert(c >= 'a' && c <= 'z');
        return value[c-'a'].content();
    }
};


struct import_format : virtual Noncopyable {
    char   *autodetect;
    char   *system;
    char   *new_format;
    size_t  new_format_lineno;
    size_t  tab;

    char *description; // (multiline) description of filter

    char *begin;

    char   *sequencestart;
    int     read_this_sequence_line_too;
    char   *sequenceend;
    char   *sequencesrt;
    char   *sequenceaci;
    char   *filetag;
    char   *autotag;
    size_t  sequencecolumn;
    int     autocreateacc;
    int     noautonames;

    char *end;

    SetVariables global_variables;                 // values of global variables
    SetVariables variable_errors;                  // user-defined errors (used when var not set)

    char *b1;
    char *b2;

    import_match *match;

    import_format();
    ~import_format();
};

class ArbImporter : virtual Noncopyable {
    import_format *ifo;  // main input format
    import_format *ifo2; // symlink to input format

    GBDATA *gb_import_main; // import database

    RootCallback after_import_cb;

    StrArray filenames;
    int      current_file_idx;

    FILE *in;

    GBDATA *gb_main_4_nameserver; // main DB (needed to auto-select correct nameserver-settings)

    GB_ERROR load_format(AW_root *awr);
    void unload_format() {
        delete ifo;  ifo  = NULp;
        delete ifo2; ifo2 = NULp;
    }

public:
    explicit ArbImporter(const RootCallback& after_import_cb_)
        : ifo(NULp),
          ifo2(NULp),
          gb_import_main(NULp),
          after_import_cb(after_import_cb_),
          current_file_idx(0),
          in(NULp),
          gb_main_4_nameserver(NULp)
    {
        gb_import_main = GB_open("noname.arb", "wc");
        awti_assert(gb_import_main);
    }

    ~ArbImporter() {
        if (gb_import_main) GB_close(gb_import_main);
        unload_format();
        awti_assert(!in);
    }

    GB_ERROR read_format(const char *file);
    void     detect_format(AW_root *root);
    const import_format *peek_format() const { return ifo; }

    int       next_file();
    char     *read_line(int tab, char *sequencestart, char *sequenceend);
    GB_ERROR  read_data(char *ali_name, int security_write, FieldTransfer::RuleSetPtr ruleset);

    void set_db_4_nameserver(GBDATA *gb_main) { gb_main_4_nameserver = gb_main; }

    GB_ERROR import_data(AW_root *awr, const char *mask, bool keep_found_IDs);
    void     import_and_continueOnSuccess(AW_window *aww);

    GBDATA *peekImportDB() {
        return gb_import_main;
    }
    GBDATA *takeImportDB() {
        GBDATA *gbm    = gb_import_main;
        gb_import_main = NULp;
        return gbm;
    }

    void detectAvailableFields(StrArray& fields, FieldsToScan whatToScan);
};


#else
#error awti_imp_local.hxx included twice
#endif // AWTI_IMP_LOCAL_HXX

