/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/***************************************************************************
 *            macrowindow.cc
 *
 *  Fri Aug 31 12:27:45 CEST 2007
 *  Copyright 2007 Lars Bisballe Jensen and Bent Bisballe Nyeng
 *  elsenator@gmail.com and deva@aasimon.org
 ****************************************************************************/

/*
 *  This file is part of Pracro.
 *
 *  Pracro is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  Pracro is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Pracro; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
 */
#include "macrowindow.h"

#include <QVBoxLayout>
#include <QDomDocument>
#include <QDomElement>
#include <QByteArray>
#include <QApplication>

#include "messagebox.h"
#include "widgets/widget.h"
#include "widgets/window.h"
#include "lua.h"
#include "resumewidget.h"

#include "debug.h"

extern QString cpr;
extern QString user;
extern QString host;
extern quint16 port;

MacroWindow::MacroWindow(NetCom &n, QDomNode &xml_doc, QString templ,
                         bool is_static, bool compact)
  : Collapser(), netcom(n)
{
  this->is_static = is_static;

  DEBUG(macrowindow, "Constructor %p\n", this);

  mainwidget = NULL;
  lua = new LUA(&mainwidget);

  waschanged = false;

  this->templ = templ;

  setCollapsedWidget(new ResumeWidget(compact));

  update(xml_doc);

  setCollapsed(!is_static);
  active = true;

  connect(this, SIGNAL(doneCollapsing()), this, SLOT(collapsed()));
}

MacroWindow::~MacroWindow()
{
  clear();
  delete collapsedWidget();
}

void MacroWindow::update(QDomNode &node)
{
  clear();
  lua->clear();

  initMacro(node);

  if(mainwidget) setExpandedWidget(mainwidget->qwidget());
  else setExpandedWidget(NULL);
}

void MacroWindow::initMacro(QDomNode &node)
{
  QDomElement elem = node.toElement();

  if(elem.tagName() == "macro") {

    // Assign the macro name and version to QStrings for use when comitting
    macro = elem.attribute("name", "");
    version = elem.attribute("version", "");

  } else if(elem.tagName() == "scripts") {
    // Nothing to do here
  } else if(elem.tagName() == "resume") {
    QString resume = elem.text();
    ResumeWidget::state_t state = ResumeWidget::OLD;
    if(elem.hasAttribute("state")) {
      if(elem.attribute("state") == "old") state = ResumeWidget::OLD;
      if(elem.attribute("state") == "new") state = ResumeWidget::NEW;
      if(elem.attribute("state") == "dirty") state = ResumeWidget::DIRTY;
    }

    collapse();
    ((ResumeWidget*)collapsedWidget())->setText(resume, state);
  } else if(elem.tagName() == "script") {

    lua->runScript(elem.text(), NULL, "preload");
  
  } else if(elem.tagName() == "widgets") {

    if(mainwidget) {
      WARN(macrowindow,
           "WARNING: mainwidget already exists! Calling clear().\n");
      clear();
    }

    DEBUG(mainwindow, "----------------------Before--------------------------");

    Window *window = new Window(elem, this);

    DEBUG(mainwindow, "----------------------After--------------------------");

    connect(window, SIGNAL(wasChanged()), this, SLOT(macroChanged()));
    macrotitle = elem.attribute("caption");

    mainwidget = window;

    // Moved to expandWrapper (validation bugfix)
    //    mainwidget->setValues();
    if(is_static) mainwidget->setValues();

    if(waschanged == true) macroChanged();

    return; // No further recursion here.
  }

  QDomNodeList children = node.childNodes();

  for (int i=0; i<children.count();i++) {
    QDomNode child = children.at(i);
    initMacro(child);
  }
}

bool MacroWindow::doCommit()
{
  if(mainwidget->valid()) {
    QVector< Widget* > wlist;
    if(mainwidget) wlist = mainwidget->widgetList();
    QDomDocument doc = netcom.send(wlist, templ, macro, version);

    QDomNodeList nl = doc.documentElement().childNodes();
    QDomNode n = nl.at(0); // There can be only one! (Swush, flomp)
  
    if(n.toElement().tagName() == "error") {
      QMessageBox::critical(this, "Server Error", "Server Error: " +
                            n.toElement().text());
      return false;
    }

    qApp->processEvents();

    collapse();
    emit updateOnCommit();
    //    setCollapsed(true);

    return true;
  } else {
    MessageBox::critical(NULL, "Fejl",
                         "Makroen " + macrotitle +
                         " er ikke udfyldt korrekt, pr�v igen.\n",
                         MessageBox::Ok);

    return false;
  }
}

void MacroWindow::commit()
{
  doCommit();
}

void MacroWindow::cancel()
{
  collapseWrapper();
}

void MacroWindow::expandWrapper()
{
  if(!isCollapsed()) return;

  waschanged = false;
  
  QDomDocument xml_doc = netcom.send(templ, macro);
  
  // Initiate the new macro window with the xml document and push
  //  it to the window list
  QDomNodeList templates = xml_doc.documentElement().childNodes();

  // There can be only one! (Swush, flomp)
  QDomNode templatenode = templates.at(0);
  QDomNodeList macronodes = templatenode.childNodes();
  for(int j = 0; j < macronodes.count(); j++) {
    QDomNode macronode = macronodes.at(j);
    
    if(true || macronode.childNodes().count()) {
      // macrowindows.push_back( new MacroWindow( netcom, macronode ) );
      QDomElement elem = macronode.toElement();
      
      if(elem.tagName() == "macro") {
        
        // Assign the macro name and version to QStrings for use when comitting
        QString macroname;
        if(elem.hasAttribute("name")) {
          if(elem.attribute("name") == macro) {
            // update me!
            initMacro(macronode);
          }
        }
      }
    }
  }
  if(mainwidget) setExpandedWidget(mainwidget->qwidget());
  expand();

  // Set values here, to be sure that the widgets are visible and thereby
  //  validate correctly.
  if(mainwidget) mainwidget->setValues();

  // Set keyboard focus on the first focusable widget in the macro.
  QVector< Widget* > widgets;
  if(mainwidget) widgets = mainwidget->widgetList(true);
  QVector< Widget* >::iterator i = widgets.begin();
  while (i != widgets.end()) {
    if(*i) {
      Widget* w = *i;
      if(w->setKeyboardFocus()) break;
    }
    i++;
  }

}

void MacroWindow::collapseWrapper()
{
  if(isCollapsed()) return;

  if(waschanged) {
    switch(MessageBox::warning(NULL,
                               "Gem �ndringerne i makroen?",
                               "Du har valgt at lukke makroen " +
                               macrotitle + ".\n"
                               "�nsker du at gemme inden du lukker?",
                               MessageBox::Save | MessageBox::Close |
                               MessageBox::Cancel)) {
    case MessageBox::Save:
      if(doCommit()) {
        setCollapsed(true);        
      } else {
        MessageBox::critical(NULL, "Fejl",
                             "Makroen " + macrotitle +
                             "  er ikke udfyldt korrekt, pr�v igen.\n",
                             MessageBox::Ok);
      }
      break;
    case MessageBox::Close:
      collapse();
      break;
    case MessageBox::Cancel:
    default:
      break;
    }
  } else {
    collapse();
  }
}

void MacroWindow::toggleMacro()
{
  if(!active) return;
  if(isCollapsed()) {
    expandWrapper();
  } else {
    collapseWrapper();
  }
}

void MacroWindow::macroChanged()
{
  DEBUG(macrowindow, "This macro was changed!\n");
  emit macroHasChanged();
  waschanged = true;
}

void MacroWindow::setActive(bool active)
{
  if(this->active == active) return;

  this->active = active;
  setEnabled(active);

  emit activationChanged(active);
}

void MacroWindow::clear()
{
  //  DEBUG(macrowindow, "clear %p\n", this);
  setExpandedWidget(NULL);

  if(mainwidget) delete mainwidget;
  mainwidget = NULL;

  //  lua->clear();
}

void MacroWindow::collapsed()
{
  DEBUG(macrowindow, "collapsed %p\n", this);
  clear();
}