#include "Panel_sequence.h"

#include "User.h"

#include "Panel_sequence_editor.h"
#include "Model_impl.h"
#include "Bond_detector.h"

namespace MM
{

Panel_sequence::
Panel_sequence ()
:
    Panel ("Sequence", "bottom")
{
    setupUi (this);

    checkBox_threading->hide();

    pushButton_New->hide();
    comboBox->hide();
    pushButton_Delete->hide();

    connect (pushButton_Apply,      SIGNAL (clicked ()),
             this,                  SLOT   (apply ()));

    connect (pushButton_Cancel,     SIGNAL (clicked ()),
             this,                  SLOT   (cancel ()));

}

void Panel_sequence::
add_residue (Text const & name)
{
    to_user().status (name);

    QString file = name + ".mlm";
    QDir    dir  = Panel_sequence_editor::singleton()->repository ();

    if (dir.exists(file))
        file = dir.absoluteFilePath (file);
    else
    {
        Text message ("No file ");
        message += dir.absoluteFilePath (file);
        to_user().error (message);
        return;
    }

    Model_impl model;
    model.load (file, "auto detect");

    if (comboBox_Alias->currentText() == "Short alias")
    {
        if (model.kit().has_short_alias())
            textEdit->insertHtml (model.kit().short_alias());

        else if (model.kit().has_alias())
        {
            QString residue;
            QString line = textEdit->toPlainText();
            if (line.size() > 0 && line.at(line.size()-1) != ' ')
                residue += " ";
            residue += model.kit().alias();
            residue += " ";
            textEdit->insertHtml (residue);
        }
        else
        {
            Text message;
            message += "Model '";
            message += name;
            message += "' does not have alias.";
            to_user().error (message);
        }
    }
    else
    {
        if (model.kit().has_alias())
        {
            QString residue;
            QString line = textEdit->toPlainText();
            if (line.at(line.size()-1) != ' ')
                residue += " ";
            residue += model.kit().alias();
            residue += " ";
            textEdit->insertHtml (residue);
        }
        else if (model.kit().has_short_alias())
            textEdit->insertHtml (model.kit().short_alias());
        else
        {
            Text message;
            message += "Model '";
            message += name;
            message += "' does not have alias.";
            to_user().error (message);
        }
    }

    if (checkBox_Auto_apply->checkState() == Qt::Checked)
        apply ();
}

void Panel_sequence::
apply ()
{
    int                     i, index = 0;
    Array_of_own <Model>    model_list;
    //Array_of_ref <Model>    seq_list;
    Array <Text>            seq_list;
    QDir    dir  = Panel_sequence_editor::singleton()->repository ();

    Panel_sequence_editor * editor_panel = 
        Panel_sequence_editor::singleton();

    QStringList filters;
    filters << "*.mlm";
    QFileInfoList prototype = editor_panel->repository ().
        entryInfoList (filters, QDir::Files, QDir::Name);

    // list of resudues prototypes
    for (i=0;  i<prototype.size();  ++i)
    {
        model_list.push_back (new Model_impl);

        QFileInfo const & info = prototype.at(i);
        Text file = info.absoluteFilePath();
        model_list.back().load (file, "auto detect");
    }

    // list of resudues from the seq-text and prototypes
    QString seq_text = textEdit->toPlainText();
    
    for (i=0;  i<seq_text.size();)
    {
        if (seq_text.at(i) == ' ' || seq_text.at(i) == '\n')
        {
            ++i;
            continue;
        }

        Text    alias = "";
        bool    res_found = false;

        for (int j=0;  j<model_list.size();  ++j)
        {
            Model_kit const & kit = model_list[j].kit();

            if (comboBox_Alias->currentText() == "Short alias" 
                && kit.has_short_alias())

                alias = kit.short_alias();
            else if (kit.has_alias())
                alias = kit.alias();
            else
            {
                Text message;
                message += "Model '";
                message += prototype.at(j).absoluteFilePath();
                message += "' does not have alias.";
                to_user().error (message);
                return;
            }

            index = seq_text.indexOf (alias, i, Qt::CaseInsensitive);

            if (i==index)
            {
                res_found = true;
                //seq_list.push_back (model_list[j]);
                seq_list.push_back(prototype.at(j).absoluteFilePath());
                i += alias.size();
                break;
            }
        }
        if (!res_found)
        {
            Text message;
            message += "Alias for '";
            message += seq_text.section('\n', i);
            message += "' was not found.";
            to_user().error (message);
            return;
        }
    }

    // apply list of resudues
    //QAbstractButton *checkedButton = button_group_->checkedButton ();
    //CHECK("Some button always checked.", checkedButton != 0);
    //QString action = checkedButton->text();
    Sequence_editor & editor = model().kit().sequence_editor ();

    // Define current residue
    int mol_n = editor.molecule_count() - 1;
    int res_n = mol_n >= 0 ? editor.molecule (mol_n).residue_count() - 1 : -1;

    //QModelIndex currentIndex = tableView_Sequence->currentIndex ();
    //if (currentIndex.isValid ())
    //{
    //    mol_n_ = currentIndex.row();
    //    res_n_ = currentIndex.column() - 1;

    //    if (res_n_ >= editor.molecule(mol_n_).residue_count())
    //        res_n_ =  editor.molecule(mol_n_).residue_count() - 1;
    //}

    // Apply
    for (i=0;  i<seq_list.size();  ++i)
    {
        if (mol_n == -1)
        {
            editor.new_molecule (seq_list[i]);
            ++mol_n;
            res_n = editor.molecule(mol_n).residue_count() - 1;
        }
        else
        {
            res_n = editor.molecule(mol_n).residue_count() - 1;
            int added = editor.append (mol_n, res_n, seq_list[i]);
            res_n += added;
            //select res_n
        }

        int current_conformation_n = 
            editor_panel->spinBox_Conformation_N->value ();

        if (editor_panel->spinBox_Conformation_N->isEnabled()
            && res_n > 0) //fix res_n >= 0
        {
            Molecule     & mol          = editor.molecule (mol_n);
            Torsion_list & torsion_list = 
                editor_panel->conformational_file_.torsion_list();

            torsion_list.apply (mol, res_n - 1, current_conformation_n);

            ++current_conformation_n;
            if (current_conformation_n >= editor_panel->conformational_file_.
                torsion_list().residue_count())
                current_conformation_n = 0;

            editor_panel->spinBox_Conformation_N->
                setValue (current_conformation_n);
        }
    }

    // B-DNA ------------------------------------------------{
    QString dir_name = dir.dirName ();
    to_user().status (dir_name);
    if (dir_name.contains("- B-DNA"))
    {
        Bond_detector detector (model());
        detector.execute ();
    }
    // B-DNA ------------------------------------------------}

    textEdit->clear();
    //renew_current_model (*current_model_);
    model().kit().visual().fit_to_screen();

    if (model().kit().has_force_field())
        model().kit().set_force_field (model().kit().force_field().name ());
}

void Panel_sequence::
cancel ()
{
    textEdit->clear();
}

//void Panel_sequence::
//keyPressEvent (QKeyEvent * event)
//{
//}

}//MM
