/***************************************************************************
 *   Copyright (C) 2004 - 2005 by Raphael Langerhorst                      *
 *   raphael-langerhorst@gmx.at                                            *
 *                                                                         *
 *   Permission is hereby granted, free of charge, to any person obtaining *
 *   a copy of this software and associated documentation files (the       *
 *   "Software"), to deal in the Software without restriction, including   *
 *   without limitation the rights to use, copy, modify, merge, publish,   *
 *   distribute, sublicense, and/or sell copies of the Software, and to    *
 *   permit persons to whom the Software is furnished to do so, subject to *
 *   the following conditions:                                             *
 *                                                                         *
 *   The above copyright notice and this permission notice shall be        *
 *   included in all copies or substantial portions of the Software.       *
 *                                                                         *
 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       *
 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    *
 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*
 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR     *
 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR *
 *   OTHER DEALINGS IN THE SOFTWARE.                                       *
 ***************************************************************************/

#include "GweSimpleController.h"
#include "GDataController.h"

#include <GObject.h>
#include <GForm.h>
#include <GElement.h>
#include <GElementID.h>
#include <GVector3.h>
#include <GMatrix44.h>


using namespace GCS;
 
namespace GWE
{

GweSimpleDataController::GweSimpleDataController()
{
  this->ElementListMutex = new QMutex();
  GCS::GElementID::addFreeIDRange(1,4294967295); // init to 2^32 - 1
}

GweSimpleDataController::~GweSimpleDataController()
{
  delete this->ElementListMutex;
  //@todo proper parking and storing (into DB?) of all elements!!!!!!!!!
}

bool GweSimpleDataController::add(GElement* element)
{
  this->ElementListMutex->lock();
  Elements.prepend(element);
  this->ElementListMutex->unlock();
  qDebug("Added element with ID " + QString::number(element->getElementID().getID()));
  if (element->isParked())
    element->executeElement();
  emit elementAdded(element->getElementID().getID());
//   qDebug("elementAdded emitted");
  return true;
}

bool GweSimpleDataController::writeOpenElementToStorage(const GCS::GElementID& id)
{
  return true;
}

GElement* GweSimpleDataController::getElement(const GElementID& id) const
{
  this->ElementListMutex->lock();
  QPtrListIterator<GElement> it( Elements );
  GElement* element;
  while( (element = it.current()) != 0)
  {
    ++it;
    if (element->getElementID() == id)
    {
      this->ElementListMutex->unlock();
      return element;
    }
  }
  this->ElementListMutex->unlock();
  return NULL;
}

const GElement* GweSimpleDataController::read(const GElementID& id) const
{
  return getElement(id);
}

QValueList<GCS::GElementID> GweSimpleDataController::getChildren(const GCS::GElementID& parent) const
{
  this->ElementListMutex->lock();
  QPtrListIterator<GElement> it( Elements );
  QValueList<GCS::GElementID> children;
  GElement* element;
  while( (element = it.current()) != 0)
  {
    ++it;
    if (element->getObject()->getParent() == parent && element->getObject()->getParent() != element->getElementID())
    {
      children.append(element->getElementID());
    }
  }
  this->ElementListMutex->unlock();
  return children;
}

GElement* GweSimpleDataController::open(const GElementID& id)
{
  GElement* element = getElement(id);
  if (element)
  {
    if (element->isParked())
      element->executeElement();
    emit this->elementOpened(element->getElementID().getID());
  }
  else
  {
    qWarning(QString("Could not open element with ID %1").arg(id.getID()));
  }
  
  return element;
}

GElement* GweSimpleDataController::getOpenElement(const GElementID& id)
{
  GElement* element = getElement(id);
  return element;
}

const QValueList<GCS::GElementID> GweSimpleDataController::getListOfOpenElements()
{
  return getListOfAllElements();
}

const QValueList<GCS::GElementID> GweSimpleDataController::getListOfAllElements()
{
  QValueList<GCS::GElementID> list;
  this->ElementListMutex->lock();
  QPtrListIterator<GElement> it( Elements );
  GElement* element;
  while( (element = it.current()) != 0)
  {
    ++it;
    list.append((*it)->getElementID());
  }

  this->ElementListMutex->unlock();
  return list;
}

bool GweSimpleDataController::close(const GCS::GElementID& element)
{
  emit this->elementClosed(element);
  return true;
}

bool GweSimpleDataController::postDelete(const GElementID& element_id)
{
  close(element_id);
  GElement* element = getElement(element_id);
  element->deleteLater();
//   connect(element,SIGNAL(destroyed()),this,SLOT(elementDeleted()))
  this->ElementListMutex->lock();
  Elements.remove(element);
  this->ElementListMutex->unlock();
  emit elementDeleted(element_id);
  return true;
}

void GweSimpleDataController::shutdown()
{
  qDebug("Simple Data Controller shutting down.");
}

// GweSimpleController implementation

GweSimpleController::GweSimpleController()
: GweController(new GweSimpleDataController(),this,"simple data controller")
{
  connect(Data,SIGNAL(elementAdded(const GCS::GElementID& )),this,SLOT(connectElement(const GCS::GElementID& )));
}

GweSimpleController::~GweSimpleController()
{
}

void GweSimpleController::connectElement(const GElementID& id)
{
  GElement* element = Data->open(id);
  if (element)
  {
//     qDebug(QString("connecting signals and slots for element %1 !").arg(id.getID()));
//     connect(element,SIGNAL(parentChanged(GCS::GElement*, const GCS::GElementID&, const GCS::GElementID& )),
//               this,SLOT(elementReparented(GCS::GElement*, const GCS::GElementID&, const GCS::GElementID& )));
    
    connect(element,SIGNAL(childElementCreated(GCS::GElement* )),
              this,SLOT(newElementCreated(GCS::GElement* )));
    connect(element,SIGNAL(childElementRemoved(const GCS::GElementID& )),
              this,SLOT(elementRemoved(const GCS::GElementID& )));
    
    connect(element,SIGNAL(radiateInfluence(const GCS::GElementInfluence& )),
              this,SLOT(radiateInfluence(const GCS::GElementInfluence& )));
    connect(element,SIGNAL(sendInfluence(const GCS::GElementID&, const GCS::GElementInfluence& )),
              this,SLOT(routeInfluence(const GCS::GElementID&, const GCS::GElementInfluence& )));
    connect(element,SIGNAL(formChanged(const GCS::GForm& )),
            this,SLOT(handleReparenting()));
    Data->close(id);
  }
  else
  {
    qWarning(QString("could not connect element %1 !").arg(id.getID()));
  }
}

void GweSimpleController::newElementCreated(GElement* element)
{
  Q_CHECK_PTR(element);
  if (element)
  {
    qDebug("new element created, adding to data");
    Data->add(element);
  }
  else
    qWarning("received new element, but element was NULL");
}

void GweSimpleController::elementRemoved(const GElementID& ID)
{
  Data->close(ID);
  Data->postDelete(ID);
}

void GweSimpleController::elementReparented(GCS::GElement* element, const GCS::GElementID& oldParent, const GCS::GElementID& newParent)
{
  //
}


}


syntax highlighted by Code2HTML, v. 0.9.1