#include "Main_window.h"

#include "Args.h"
//#include "Model.h"
//#include "Model_kit.h"
#include "Model_RM_window.h"
#include "Project.h"
#include "Program_title.h"

#include "ui_Main_window.h"
#include "Path.h"
#include "Log.h"
#include "File_text_output.h"

#include "string_replace.h"

#include <QToolButton>
#include <QTabBar>
#include <QFileInfo>

#include <QMdiSubWindow>
#include <QVariant>

namespace MM
{

Main_window::
Main_window ()
:
    player_on_(false)
{
    setupUi (this);
    setup_log ();

    setIconSize  (QSize (32, 32));
    QIcon default_window_icon;
    default_window_icon.addFile((Path::icon() + "icon-16.png").c_str());
    default_window_icon.addFile((Path::icon() + "icon-24.png").c_str());
    default_window_icon.addFile((Path::icon() + "icon-32.png").c_str());
    qApp->setWindowIcon (default_window_icon);


    vboxLayout->setContentsMargins (1,1,1,1);

    tabBar = new QTabBar (frame_models);
    tabBarLayout = new QVBoxLayout (frame_models);
    tabBarLayout->addWidget (tabBar);
    tabBarLayout->setContentsMargins (0, 0, 0, 0);

    // Mdi Area
    
    //class MyMdiArea : public QMdiArea
    //{
    //public:
    //    MyMdiArea (QWidget * parent = 0) : QMdiArea (parent) {}
    //    void            paintEvent (QPaintEvent * event)     {}
    //};
    //MDI_panel = new MyMdiArea (MDI_frame);

    MDI_panel = new QMdiArea (MDI_frame);
    MDI_panel->setObjectName (QString::fromUtf8("MDI_panel"));
    MDI_panel->setFrameShape (QFrame::StyledPanel); //NoFrame

    QString name (program_title ());

#ifdef ASCALAPH
    //if (name.contains ("Ascalaph",  Qt::CaseInsensitive))
    {
        double k = 1.7;
        //double k = 1.6;
        //double k = 2;
        //MDI_panel->setBackground (QBrush (QColor (int(k*100), int(k*95), int(k*85))));
        MDI_panel->setBackground (QBrush (QColor (int(k*100), int(k*98), int(k*90))));
    }
#else
    //else if (name.contains ("Abalone",  Qt::CaseInsensitive))
    {
        float k = 1.05f;
        //float k = 1.1;

        //float k = 1.7;
        //float k = 0.9;
        ////MDI_panel->setBackground (QBrush (QColor (int(k*227), int(k*222), int(k*200))));
        //MDI_panel->setBackground (QBrush (QColor (int(k*227.), int(k*222.), int(k*200.))));

        //MDI_panel->setBackground (QBrush (QColor (int(k*216.), int(k*202.), int(k*179.))));
        MDI_panel->setBackground (QBrush (QColor(int(k*210), int(k*210), int(k*200))));
    }
    //MDI_panel->setAutoFillBackground (true);
    setWindowTitle ("Abalone");
#endif
    setWindowTitle (name);

    MDIboxLayout = new QVBoxLayout (MDI_frame);
    MDIboxLayout->addWidget (MDI_panel);
    MDIboxLayout->setContentsMargins (0, 0, 0, 0);

    connect (MDI_panel, SIGNAL (subWindowActivated (QMdiSubWindow*)),
             this,      SLOT   (sub_window_activated (QMdiSubWindow*)));
    
    connect (tabBar,    SIGNAL (currentChanged (int)),
             this,      SLOT   (tab_bar_activated (int)));
    

    // Ascalaphus

    QHBoxLayout *boxLayout = new QHBoxLayout (MDI_panel);
    boxLayout->setContentsMargins (0, 0, 0, 0);
    label = new QLabel (MDI_panel);

    if (name.contains ("Ascalaph",  Qt::CaseInsensitive))
    {
        label->setPixmap (QPixmap (Path::images() + "Ascalaphus_1_700.png"));
    }
    else if (name.contains ("Abalone",  Qt::CaseInsensitive))
    {
        label->setPixmap (QPixmap (Path::images() + "Abalone.png"));
    }

    label->setAlignment (Qt::AlignCenter);

    boxLayout->addWidget (label);


    // Close buttons for panels

    QToolButton * close_left = new QToolButton;
    close_left->setText ("x");
    tabWidget_left->setCornerWidget (close_left);
    //tabWidget_left->setCornerWidget (close_left, Qt::TopLeftCorner);
    connect (close_left,        SIGNAL(pressed()),
             this,              SLOT(remove_left_panel()));

    QToolButton * close_right = new QToolButton;
    close_right->setText ("x");
    tabWidget_right->setCornerWidget (close_right);
    connect (close_right,       SIGNAL(pressed()),
             this,              SLOT(remove_right_panel()));

    QToolButton * close_middle = new QToolButton;
    close_middle->setText ("x");
    tabWidget_middle->setCornerWidget (close_middle);
    connect (close_middle,      SIGNAL(pressed()),
             this,              SLOT(remove_middle_panel()));

    connect (tabWidget_middle,  SIGNAL(currentChanged (int)),
             this,              SLOT(middle_panel_current_changed(int)));

    QToolButton * close_bottom = new QToolButton;
    close_bottom->setText ("x");
    tabWidget_bottom->setCornerWidget (close_bottom);
    connect (close_bottom,      SIGNAL(pressed()),
             this,              SLOT(remove_bottom_panel()));
    

    // remove temporary panels

    while (tabWidget_left->count () != 0)
        remove_left_panel();

    while (tabWidget_right->count () != 0)
        remove_right_panel();

    //while (tabWidget_bottom->count () != 0)
    //    remove_bottom_panel();

    QToolBar *tool_bar;
    
    // Right Tool Bar

    tool_bar = new QToolBar ("Fast View");
    addToolBar (Qt::RightToolBarArea, tool_bar);
    tool_bar_.push_back (tool_bar);

    tool_bar = new QToolBar ("Fast Edit");
    addToolBar (Qt::RightToolBarArea, tool_bar);
    tool_bar_.push_back (tool_bar);

    tool_bar = new QToolBar ("Fast Compute");
    addToolBar (Qt::RightToolBarArea, tool_bar);
    tool_bar_.push_back (tool_bar);

    // Top Tool Bar

    tool_bar = new QToolBar ("File");
    addToolBar (tool_bar);
    tool_bar_.push_back (tool_bar);

    //tool_bar = new QToolBar ("Edit");
    //addToolBar (tool_bar);
    //tool_bar_.push_back (tool_bar);

    tool_bar = new QToolBar ("Build");
    addToolBar (tool_bar);
    tool_bar_.push_back (tool_bar);
    tool_bar = new QToolBar ("Windows");
    addToolBar (tool_bar);
    tool_bar_.push_back (tool_bar);

    tool_bar = new QToolBar ("Help");
    addToolBar (tool_bar);
    tool_bar_.push_back (tool_bar);

    // Left Tool Bar

    tool_bar = new QToolBar ("Edit");
    addToolBar (Qt::LeftToolBarArea, tool_bar);
    tool_bar_.push_back (tool_bar);

    //tool_bar = new QToolBar ("Slow View");
    //addToolBar (Qt::LeftToolBarArea, tool_bar);
    //tool_bar_.push_back (tool_bar);

    tool_bar = new QToolBar ("Select");
    addToolBar (Qt::LeftToolBarArea, tool_bar);
    tool_bar_.push_back (tool_bar);

    tool_bar = new QToolBar ("User");
    addToolBar (Qt::LeftToolBarArea, tool_bar);
    tool_bar_.push_back (tool_bar);

    //qApp->setStyleSheet ("QMenu { font: bold; } "); 

    status = new QLabel ("Status");
    status->setAlignment (Qt::AlignHCenter);
    statusBar()->addWidget (status, 1); 
  
    // Top Tool Bar

    //QMenuBar * menuBar = new QMenuBar;
    //
    //menuBar->addMenu ("&File");
    //menuBar->addMenu ("&Edit");
    //menuBar->addMenu ("&View");
    ////menuBar->addMenu ("");

    //setMenuWidget (menuBar);

    toolButton_Stop   -> setIcon (QIcon((Path::icon() + "Player/Stop.png")));
    toolButton_Back   -> setIcon (QIcon((Path::icon() + "Player/Back.png")));
    toolButton_Tune   -> setIcon (QIcon((Path::icon() + "Player/Tune.png")));
    toolButton_Run    -> setIcon (QIcon((Path::icon() + "Player/Run.png")));
    toolButton_Start  -> setIcon (QIcon((Path::icon() + "Player/Start.png")));
    toolButton_Forward-> setIcon (QIcon((Path::icon() + "Player/Forward.png")));
    toolButton_Pause  -> setIcon (QIcon((Path::icon() + "Player/Pause.png")));

    toolButton_Stop   -> setEnabled (false);
    toolButton_Back   -> setEnabled (false);
    toolButton_Tune   -> setEnabled (false);
    toolButton_Run    -> setEnabled (false);
    toolButton_Start  -> setEnabled (false);
    toolButton_Forward-> setEnabled (false);
    toolButton_Pause  -> setEnabled (false);

    trajectory_slider-> setEnabled (false);
    trajectory_slider->hide();

//    showMaximized ();

}

QWidget * Main_window::
current_model_window ()
{
    if (MDI_panel->currentSubWindow () == 0)
        return 0;                                   //fix to New_model()
    //{
        //Project::singleton().current_model();
        //QWidget * subWindow = MDI_panel->currentSubWindow ();
        //qApp->processEvents(QEventLoop::ExcludeSocketNotifiers);
        //return subWindow;

        ////New_model();
    //}

    return MDI_panel->currentSubWindow ()->widget();
}

void Main_window::
tab_bar_activated (int tab)
{
    //QVariant        var = tabBar->tabData (tab);
    //int             id  = var.toInt ();
    //QMdiSubWindow * win = (QMdiSubWindow *)id;

    //QMdiSubWindow * win = dynamic_cast<QMdiSubWindow *> (tabID [tab]);
    QVariant        var = tabBar->tabData (tab);
    int             id  = var.toInt ();
    QMdiSubWindow * win = dynamic_cast<QMdiSubWindow *> (tabID [id]);

    if (win == 0)
        return;

    //win->hide ();

    MDI_panel->repaint ();

    ////win->setEnabled (false);
    //win->setUpdatesEnabled(false);
    //win->widget()->setUpdatesEnabled(false);
    ////win->blockSignals (true);

    //MDI_panel->setUpdatesEnabled(false);
    //MDI_panel->blockSignals (true);

    MDI_panel->setActiveSubWindow (win);
    //win->setFocus ();

    //MDI_panel->blockSignals (false);
    //MDI_panel->setUpdatesEnabled(true);

    ////win->blockSignals (false);
    //win->widget()->setUpdatesEnabled(true);
    //win->setUpdatesEnabled(true);
    ////win->setEnabled (true);

    //win->update();
    //MDI_panel->update();
    MDI_panel->repaint ();

    //win->show ();

    //QMdiSubWindow * win = qvariant_cast <QMdiSubWindow *> (var);
    //QMdiSubWindow * win = qVariantValue <QMdiSubWindow *> (var);

    //QMdiSubWindow *win = tabBar->tabData(tab).value <QMdiSubWindow *> ();
    //MDI_panel->setActiveSubWindow (win);
}

void Main_window::
sub_window_activated (QMdiSubWindow * win) 
{
    if (win == 0) 
        return;

    Model_RM_window * RM_window = 
        dynamic_cast <Model_RM_window *> (win->widget());
    //if (&Project::singleton().current_model() != &RM_window->model())
    //MDI_panel->blockSignals (true);
    //RM_window->blockSignals (true);
    Project::singleton().set_current_model (RM_window->model());
    //RM_window->blockSignals (false);
    //MDI_panel->blockSignals (false);

    int wID = subWindowID [win];

    for (int i=0;  i<tabBar->count();  ++i)
    {
        //if (qVariantValue  <QMdiSubWindow *> (tabBar->tabData(i)) == (int)win)

        QVariant        var = tabBar->tabData (i);
        int             id  = var.toInt ();

        //if (tabBar->tabData(i).toInt() == (int)win)
        //if (id == (int)win)
        if (id == wID)
        {
            tabBar->blockSignals (true);
            tabBar->setCurrentIndex (i);
            tabBar->blockSignals (false);
            return;
        }
    }

    //FLAW ("Can not find tabBar.");
}

void Main_window::
remove_tab (QObject * win)
{
    if (win == 0) 
        return;

    int wID = subWindowID [win];

    for (int i=0;  i<tabBar->count();  ++i)
    {
        QVariant        var = tabBar->tabData (i);
        int             id  = var.toInt ();

        //if (id == (int)(QObject*)win)
        if (id == wID)
        {
            tabBar->removeTab (i);
            subWindowID.remove (win);
            tabID.remove (wID);
            return;
        }
    }

    FLAW ("Can not remove tabBar.");
}

void Main_window::
adopt_MDI_window (QWidget *win, QString const& name)
{
    delete MDI_panel->layout ();
    delete label;
    label = 0;
    MDI_panel->repaint();

    
    //QTabWidget *tabWidget;
    //tabWidget->addTab (0, name);

    QMdiSubWindow * subWindow = MDI_panel->addSubWindow (win);
    subWindow->setWindowTitle (name);
    subWindow->setWindowIcon (QIcon((Path::icon() + "none-16.png").c_str()));   //fix

    connect (subWindow, SIGNAL (destroyed  (QObject *)),
             this,      SLOT   (remove_tab (QObject *)));

    int index = tabBar->addTab (QFileInfo (name).fileName ());

    //tabBar->setTabData (index, (int)subWindow);
    static int ID = 0;
    subWindowID [subWindow] = ID;
    tabBar->setTabData (index, ID);
    tabID [ID] = subWindow;
    ++ID;

    //subWindow->show();
    subWindow->showMaximized();

    //subWindow->setOption (QMdiSubWindow::RubberBandMove);
    //subWindow->setSystemMenu (new QMenu());
    //subWindow->systemMenu()->setIcon (QIcon());
    //subWindow->systemMenu()->addMenu ("Title");

}

void Main_window::
close_all_windows ()
{
    QList<QMdiSubWindow *> list = MDI_panel->subWindowList ();

    for (int i = 0; i < list.size(); ++i)
        list.at(i)->close ();
}

void Main_window::
remove_left_panel ()
{
    if (tabWidget_left->currentWidget()->close ())
    {
        delete tabWidget_left->currentWidget ();

        if (tabWidget_left->count() == 0)
            min_left_panel ();
    }
}

void Main_window::
min_left_panel ()
{
    QList<int> old_sizes = splitter->sizes ();
    QList<int> new_sizes;

    if (tabWidget_left->count() == 0)
    {
        new_sizes.push_back (0);
        new_sizes.push_back (old_sizes[0] + old_sizes[1]);
        new_sizes.push_back (old_sizes[2]);
    }
    else 
    {
        int min = tabWidget_left->minimumSizeHint().width();
        new_sizes.push_back (min);
        new_sizes.push_back (old_sizes[0] + old_sizes[1] - min);
        new_sizes.push_back (old_sizes[2]);
    }
    splitter->setSizes (new_sizes);
}

void Main_window::
remove_right_panel ()
{
    if (tabWidget_right->currentWidget()->close ())
    {
        delete tabWidget_right->currentWidget ();
        min_right_panel ();
    }
}

void Main_window::
min_right_panel ()
{
    QList<int> old_sizes = splitter->sizes ();
    QList<int> new_sizes;

    if (tabWidget_right->count() == 0)
    {
        new_sizes.push_back (old_sizes[0]);
        new_sizes.push_back (old_sizes[1] + old_sizes[2]);
        new_sizes.push_back (0);
    }
    else 
    {
        int min = tabWidget_right->minimumSizeHint().width();
        new_sizes.push_back (old_sizes[0]);
        new_sizes.push_back (old_sizes[1] + old_sizes[2] - min);
        new_sizes.push_back (min);
    }
    splitter->setSizes (new_sizes);
}

void Main_window::
remove_middle_panel ()
{
    QWidget * tab = tabWidget_middle->currentWidget ();

    if (tab == tab_Info || 
        tab == tab_Warn || 
        tab == tab_Log)
        return;

    if (tab->close ())
    {
        delete tab;
        min_middle_panel ();
    }
}

void Main_window::
min_middle_panel ()
{
    QList<int> old_sizes = splitter_2->sizes ();
    QList<int> new_sizes;
    int full_size = old_sizes[0] + old_sizes[1];

    if (tabWidget_middle->count() == 0)
    {
        new_sizes.push_back (full_size);
        new_sizes.push_back (0);
    }
    else 
    {
        new_sizes.push_back (full_size - 175);
        new_sizes.push_back (175);
    }
    splitter_2->setSizes (new_sizes);
}

void Main_window::
remove_bottom_panel ()
{
    if (tabWidget_bottom->currentWidget () == tab_Run)
        return;

    delete tabWidget_bottom->currentWidget ();
    min_bottom_panel ();
}

void Main_window::
min_bottom_panel ()
{
    QList<int> old_sizes = splitter_3->sizes ();
    QList<int> new_sizes;
    int full_size = old_sizes[0] + old_sizes[1];

    if (tabWidget_bottom->count() == 0)
    {
        new_sizes.push_back (full_size);
        new_sizes.push_back (0);
    }
    else 
    {
        new_sizes.push_back (full_size - 10);
        new_sizes.push_back (10);
    }
    splitter_3->setSizes (new_sizes);
}

void Main_window::
middle_panel_current_changed (int index)
{
    if (tabWidget_middle->tabIcon(index).isNull())
        return;

    QWidget * tab = tabWidget_middle->currentWidget ();

    if (tab == tab_Info || 
        tab == tab_Warn )
    {
        tabWidget_middle->setTabIcon (index, QIcon());

        //Text text;
        //text += "<br><font color=#eeeeee>"
        //"______________________________________________________________________________"
        //"</font><br>";

        // if (tab == tab_Info)
        //    info->insertHtml (text);
        // else if (tab == tab_Warn)
        //    warn->insertHtml (text);
        // else 
        //     FLAW ("Unknown tab @ Main_window::middle_panel_current_changed");
   }
}

QToolBar * Main_window::
tool_bar (QString const& title)
{
    for (int i=0;  i<tool_bar_.size();  ++i)
        if (title == tool_bar_[i]->windowTitle())
            return tool_bar_[i];

    tool_bar_.push_back (addToolBar (title));
    return tool_bar_.back();
}

QMenu * Main_window::
menu (QString const& title)
{
    for (int i=0;  i<menuBar()->actions ().count();  ++i)
    {
        QMenu * menu = menuBar()->actions().at(i)->menu();
        
        if (menu != 0)
            if (menu->title() == title)
                return menu;
    }

    QMenu * menu = menuBar()->addMenu (title);
    return menu;
}

void Main_window::
showEvent (QShowEvent * event)
{
    showMaximized ();
    QWidget::showEvent (event);
    min_middle_panel ();
    min_bottom_panel ();
    min_left_panel   ();
    min_right_panel  ();

    // hide empty tool bars

    for (int i=0;  i<tool_bar_.size();  ++i)
        if (tool_bar_[i]->actions().count() == 0)
            tool_bar_[i]->hide ();

    // remove empty menus

    for (int i=0;  i<menuBar()->actions ().count();  ++i)
    {
        QAction * action = menuBar()->actions().at(i);
        QMenu   * menu   = action->menu();
        
        if (menu != 0)
        {
            Text title = menu->title();
            //int  count = menu->actions().count();

            if (menu->isEmpty())
                //menu->hide();
                menuBar()->removeAction (action);
        }
    }
}

void Main_window::
closeEvent (QCloseEvent * event)
{
    if (player_on_)
    {
        toolButton_Stop->click();
    }

    QMainWindow::closeEvent (event);
}

void Main_window::
setup_log ()
{
    class Main_window_log : public File_text_output
    {
        QTextBrowser *  log_;
        Text            font_;

    public:
        explicit Main_window_log (QTextBrowser *log) 
        : 
            File_text_output (Path::report() +"_log.txt"), 
            log_ (log), 
            font_(" <font color=#316663>") { }

        Text_output & text  (const Text & str)
        {
            File_text_output::text (str);

            using namespace std;
            string s = str.c_str();
            string_replace (s, "\n", " <br> ");

            log_->insertHtml (font_ + s.c_str() + "</font>");
            return *this;
        }

        Text_output & line  (const Text & str)
        {
            File_text_output::line (str);

            using namespace std;
            string s = str.c_str();
            string_replace (s, "\n", " <br> ");

            log_->insertHtml (font_ + s.c_str() + "</font> <br> ");
            return *this;
        }
        
        Text_output & flush () 
        {
            File_text_output::flush ();
            log_->moveCursor (QTextCursor::End);
            log_->repaint ();
            return *this;
        }
    };

    Logger::singleton().set_output (new Main_window_log (log_browser));
    log () << "Start at " << *::argv /*Text(Path::start_dir ())*/ << "\n";
    log() << "Working folder " << Path::working() << "\n";
}

}//MM
