// =============================================================== //
//                                                                 //
//   File      : AdminGui.cxx                                      //
//   Purpose   : alignment admin GUI                               //
//                                                                 //
//   Institute of Microbiology (Technical University Munich)       //
//   http://www.arb-home.de/                                       //
//                                                                 //
// =============================================================== //

#include <AliAdmin.h>
#include <insdel.h>

#include <sel_boxes.hxx>
#include <prompt.hxx>

#include <aw_question.hxx>
#include <aw_msg.hxx>

#include <arbdbt.h>

static void alignment_vars_callback(AW_root *, AliAdmin *admin) {
    ali_assert(!GB_have_error());

    GBDATA         *gb_main  = admin->get_gb_main();
    GB_transaction  ta(gb_main);
    GBDATA         *ali_cont = GBT_get_alignment(gb_main, admin->get_selected_ali());

    if (!ali_cont) {
        GB_clear_error();
        admin->type_awar()->unmap();
        admin->len_awar()->unmap();
        admin->aligned_awar()->unmap();
        admin->security_awar()->unmap();
        admin->remark_awar()->unmap();
        admin->auto_awar()->unmap();
    }
    else {
        GBDATA *ali_len         = GB_search(ali_cont, "alignment_len",            GB_INT);
        GBDATA *ali_aligned     = GB_search(ali_cont, "aligned",                  GB_INT);
        GBDATA *ali_type        = GB_search(ali_cont, "alignment_type",           GB_STRING);
        GBDATA *ali_security    = GB_search(ali_cont, "alignment_write_security", GB_INT);
        GBDATA *ali_rem         = GB_search(ali_cont, "alignment_rem",            GB_STRING);
        GBDATA *ali_auto_format = GB_search(ali_cont, "auto_format",              GB_INT);

        admin->type_awar()    ->map(ali_type);
        admin->len_awar()     ->map(ali_len);
        admin->aligned_awar() ->map(ali_aligned);
        admin->security_awar()->map(ali_security);
        admin->remark_awar()  ->map(ali_rem);
        admin->auto_awar()    ->map(ali_auto_format);
    }

    ali_assert(!GB_have_error());
}

static void create_admin_awars(AW_root *aw_root, AW_default aw_def, AliAdmin *admin) {
    aw_root->awar_string(admin->type_name(),   "", aw_def);
    aw_root->awar_string(admin->remark_name(), "", aw_def);

    aw_root->awar_int(admin->len_name(),      0, aw_def);
    aw_root->awar_int(admin->aligned_name(),  0, aw_def);
    aw_root->awar_int(admin->security_name(), 0, aw_def);
    aw_root->awar_int(admin->auto_name(),     0, aw_def);

    RootCallback rcb = makeRootCallback(alignment_vars_callback, admin);
    admin->select_awar()->add_callback(rcb);
    rcb(aw_root);
}

static void delete_ali_cb(AW_window *, AliAdmin *admin) {
    if (aw_ask_sure("delete_ali_data", "Are you sure to delete all data belonging to this alignment?")) {
        GBDATA         *gb_main = admin->get_gb_main();
        GB_transaction  ta(gb_main);
        GB_ERROR        error   = GBT_delete_alignment(gb_main, admin->get_selected_ali());

        error = ta.close(error);
        if (error) aw_message(error);
    }
}

static void ali_checklen_cb(AW_window *, AliAdmin *admin) {
    GBDATA         *gb_main = admin->get_gb_main();
    GB_transaction  ta(gb_main);
    GB_ERROR        error   = GBT_check_data(gb_main, admin->get_selected_ali());

    error = ta.close(error);
    aw_message_if(error);
}

static void never_auto_format_ali_genom_cb(AW_window *, AliAdmin *admin) {
    if (strcmp(admin->get_selected_ali(), "ali_genom") == 0) {
        admin->auto_awar()->write_int(2); // ali_genom is always forced to "skip"
    }
}

static void ali_format_cb(AW_window *aww, AliAdmin *admin) {
    {
        GB_transaction ta(admin->get_gb_main());
        GB_ERROR       error = ARB_format_alignment(admin->get_gb_main(), admin->get_selected_ali());
        aw_message_if(error);
    }
    ali_checklen_cb(aww, admin);
}

enum CopyRenameMode {
    CRM_RENAME,
    CRM_COPY,
};

static GB_ERROR copy_rename_handler(const char *dest, AliAdmin *admin, CopyRenameMode mode) {
    ali_assert(!GB_have_error());

    GBDATA   *gb_main = admin->get_gb_main();
    char     *source  = ARB_strdup(admin->get_selected_ali()); // selected ali may change by calling GBT_rename_alignment
    GB_ERROR  error   = GB_begin_transaction(gb_main);

    if (!error) {
        switch (mode) {
            case CRM_RENAME: error = GBT_rename_alignment(gb_main, source, dest); break;
            case CRM_COPY:   error = GBT_copy_alignment  (gb_main, source, dest); break;
        }
    }
    if (!error) error = GBT_add_alignment_changekeys(gb_main, dest);

    error = GB_end_transaction(gb_main, error);

    ali_assert(!GB_have_error());
    free(source);
    return error;
}
static void copy_rename_cb(AW_window *, AliAdmin *admin, CopyRenameMode mode) {
    ResultHandler  handler  = makeResultHandler(copy_rename_handler, admin, mode);
    const char    *old_name = admin->get_selected_ali();

    switch (mode) {
        case CRM_RENAME:
            AWT_activate_prompt("Rename alignment", "Enter the new name of the alignment:", old_name, "Rename", handler, NULp, SRT_AUTOCORRECT_ALINAME);
            break;
        case CRM_COPY:
            AWT_activate_prompt("Copy alignment", "Enter the name of the new alignment:", old_name, "Copy", handler, NULp, SRT_AUTOCORRECT_ALINAME);
            break;
    }
}

static GB_ERROR create_ali_handler(const char *name, AliAdmin *admin) {
    GBDATA   *gb_main = admin->get_gb_main();
    GB_ERROR  error   = GB_begin_transaction(gb_main);
    if (!error) {
        GBDATA *gb_ali = GBT_create_new_alignment(gb_main, name, 0, 0, 0, "dna", "manually by user.");

        if (!gb_ali) error = GB_await_error();
        else         error = GBT_add_alignment_changekeys(gb_main, name);
    }
    error = GB_end_transaction(gb_main, error);
    return error;
}
static void create_ali_cb(AW_window *, AliAdmin *admin) {
    AWT_activate_prompt("Create alignment", "Enter the name of the new alignment:", "", "Create", makeResultHandler(create_ali_handler, admin), NULp, SRT_AUTOCORRECT_ALINAME);
}

AW_window *ALI_create_admin_window(AW_root *root, AliAdmin *admin) {
    if (!admin->get_window()) {
        GBDATA           *gb_main = admin->get_gb_main();
        AW_window_simple *aws     = new AW_window_simple;

        create_admin_awars(root, AW_ROOT_DEFAULT, admin);
        admin->store_window(aws);

        admin->window_init(aws, "INFO_OF_%s", "%s information");
        aws->load_xfig("ad_align.fig");

        aws->at("close");
        aws->callback(AW_POPDOWN);
        aws->create_button("CLOSE", "CLOSE", "C");

        aws->at("help");
        aws->callback(makeHelpCallback("ad_align.hlp"));
        aws->create_button("HELP", "HELP", "H");

        // button column
        aws->button_length(13);

        aws->at("delete");
        aws->callback(makeWindowCallback(delete_ali_cb, admin));
        aws->create_button("DELETE", "DELETE", "D");

        aws->at("rename");
        aws->callback(makeWindowCallback(copy_rename_cb, admin, CRM_RENAME));
        aws->create_button("RENAME", "RENAME", "R");

        aws->at("create");
        aws->callback(makeWindowCallback(create_ali_cb, admin));
        aws->create_button("CREATE", "CREATE", "N");

        aws->at("copy");
        aws->callback(makeWindowCallback(copy_rename_cb, admin, CRM_COPY));
        aws->create_button("COPY", "COPY", "C");

        aws->at("check_len");
        aws->callback(makeWindowCallback(ali_checklen_cb, admin));
        aws->create_button("CHECK_LEN", "CHECK LEN", "L");

        aws->at("align");
        aws->callback(makeWindowCallback(ali_format_cb, admin));
        aws->create_button("FORMAT", "FORMAT", "F");

        // ali selection list
        aws->at("list");
        awt_create_ALI_selection_list(gb_main, aws, admin->select_name(), "*=");

        // alignment settings
        aws->at("aligned");
        aws->create_option_menu(admin->aligned_name());
        aws->callback(makeWindowCallback(ali_checklen_cb, admin)); aws->insert_default_option("not formatted", "n", 0); // @@@ used as OPTIONMENU_SELECT_CB (see #559)
        aws->callback(makeWindowCallback(ali_format_cb, admin));   aws->insert_option("formatted", "j", 1); // @@@ used as OPTIONMENU_SELECT_CB (see #559)
        aws->update_option_menu();

        aws->at("len");
        aws->create_input_field(admin->len_name(), 8);

        aws->at("type");
        aws->create_option_menu(admin->type_name());
        aws->insert_option("dna", "d", "dna");
        aws->insert_option("rna", "r", "rna");
        aws->insert_option("pro", "p", "ami");
        aws->insert_default_option("???", "?", "usr");
        aws->update_option_menu();

        aws->at("security");
        aws->callback(makeWindowCallback(ali_checklen_cb, admin)); // @@@ used as OPTIONMENU_SELECT_CB (see #559)
        aws->create_option_menu(admin->security_name());
        aws->insert_option("0", "0", 0);
        aws->insert_option("1", "1", 1);
        aws->insert_option("2", "2", 2);
        aws->insert_option("3", "3", 3);
        aws->insert_option("4", "4", 4);
        aws->insert_option("5", "5", 5);
        aws->insert_default_option("6", "6", 6);
        aws->update_option_menu();

        aws->at("auto_format");
        aws->callback(makeWindowCallback(never_auto_format_ali_genom_cb, admin)); // @@@ used as OPTIONMENU_SELECT_CB (see #559)
        aws->create_option_menu(admin->auto_name());
        aws->insert_default_option("ask", "a", 0);
        aws->insert_option("always", "", 1);
        aws->insert_option("never", "", 2);
        aws->update_option_menu();

        aws->at("rem");
        aws->create_text_field(admin->remark_name());
    }

    return admin->get_window();
}

