/***************************************************************************
**
**  This file is part of QGpGuiTools.
**
**  This library is free software; you can redistribute it and/or
**  modify it under the terms of the GNU Lesser General Public
**  License as published by the Free Software Foundation; either
**  version 2.1 of the License, or (at your option) any later version.
**
**  This file 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 Lesser General Public
**  License for more details.
**
**  You should have received a copy of the GNU Lesser General Public
**  License along with this library; if not, write to the Free Software
**  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
**
**  See http://www.geopsy.org for more information.
**
**  Created: 2008-03-31
**  Copyright: 2008-2019
**    Marc Wathelet
**    Marc Wathelet (LGIT, Grenoble, France)
**
***************************************************************************/

#include "PropertyProxy.h"
#include "PropertyCategory.h"
#include "PropertyTab.h"
#include "PropertyWidget.h"
#include "PropertyEditor.h"

namespace QGpGuiTools {

uint PropertyProxy::_lastUniqueId=1;
uint PropertyProxy::invalidId=0;

/*!
  \class PropertyProxy PropertyProxy.h
  \brief Brief description of class still missing

  Full description of class still missing
*/

/*!
  Description of constructor still missing
*/
PropertyProxy::PropertyProxy(QObject * parent)
    : QObject(parent)
{
  _currentCategory=0;
  _currentTab=0;
  _blockUpdates=false;
}

/*!
  Description of destructor still missing
*/
PropertyProxy::~PropertyProxy()
{
  if(isActive()) { // Remove all remaining docked widgets
    PropertyEditor::instance()->saveStates();
    PropertyEditor::instance()->takeWidgets();
    PropertyEditor::instance()->hide();
  }
  for(QHash<uint, PropertyCategory *>::iterator it=_categories.begin(); it!=_categories.end(); it++) {
    delete it.value();
  }
}

uint PropertyProxy::uniqueId()
{
  return _lastUniqueId++;
}

void PropertyProxy::blockUpdates(bool b)
{
  if(_blockUpdates) {
    if(!b) {
      _blockUpdates=b;
      setValues();
      restoreStates();
    }
  } else {
    _blockUpdates=b;
  }
}

void PropertyProxy::saveStates()
{
  if(_blockUpdates) return;
  if(isActive()) {
    PropertyEditor::instance()->saveStates();
  }
}

void PropertyProxy::restoreStates()
{
  if(_blockUpdates) return;
  if(isActive()) {
    PropertyEditor::instance()->restoreStates();
  }
}

/*!
  Set widget controls from object current values.
*/
void PropertyProxy::setValues()
{
  if(_blockUpdates) return;
  for(QHash<uint, PropertyCategory *>::iterator it=_categories.begin(); it!=_categories.end(); it++) {
    it.value()->setValues();
  }
}

void PropertyProxy::setCurrentTabValues()
{
  if(_blockUpdates) return;
  _currentCategory->setValues();
}

inline bool PropertyProxy::isActive() const
{
  return PropertyEditor::instance() && PropertyEditor::instance()->proxy()==this;
}

void PropertyProxy::raiseEditor(uint category)
{
  PropertyEditor * editor=PropertyEditor::instance();
  if(!editor) {
    editor=new PropertyEditor;
    editor->setObjectName("propertyEditor");
  }
  editor->setUpdatesEnabled(false);
  editor->setProxy(this);
  editor->show();
  editor->raise();
  QHash<uint, PropertyCategory *>::iterator it=_categories.find(category);
  if(it!=_categories.end()) {
    editor->setCurrentTab(it.value()->caption());
  }
  editor->setUpdatesEnabled(true);
}

void PropertyProxy::setEditor()
{
  for(QHash<uint, PropertyCategory *>::iterator it=_categories.begin(); it!=_categories.end(); it++) {
    ExpandTabWidget * w=new ExpandTabWidget;
    it.value()->setEditor(w);
    w->setTitlePrefix(it.value()->caption() + "::" );
    PropertyEditor::instance()->addCategory(it.value()->icon(), it.value()->caption(), w);
  }
}

bool PropertyProxy::setCurrentCategory(uint category)
{
  QHash<uint, PropertyCategory *>::iterator it=_categories.find(category);
  if(it!=_categories.end()) {
    _currentCategory=it.value();
    return true;
  } else {
    _currentCategory=0;
    return false;
  }
}

bool PropertyProxy::setCurrentTab(uint tab)
{
  if(_currentCategory) {
    _currentTab=_currentCategory->find(tab);
    return _currentTab;
  } else return false;
}

PropertyWidget * PropertyProxy::currentTabWidget() const
{
  return _currentTab ? _currentTab->widget() : 0;
}

void PropertyProxy::addCategory(uint category, QString caption, QIcon icon)
{
  _currentCategory=new PropertyCategory;
  _currentCategory->setTag(category);
  _currentCategory->setCaption(caption);
  _currentCategory->setIcon(icon);
  _categories.insert(category, _currentCategory);
  if(isActive()) {
    ExpandTabWidget * w=new ExpandTabWidget;
    w->setTitlePrefix(caption + "::" );
    PropertyEditor::instance()->addCategory(icon, caption, w);
  }
}

void PropertyProxy::addTab(uint tab, QString title, PropertyWidget * w, PropertyItem * item)
{
  if(_currentCategory) {
    w->setId(tab);
    _currentTab=_currentCategory->addTab(tab, title, w, item);
    if(isActive()) {
      PropertyEditor::instance()->addTab(_currentCategory->caption(), title, w);
    }
  }
}

void PropertyProxy::addReference(PropertyItem * item)
{
  if(_currentTab) _currentTab->addReference(item);
}

/*!
  Returns true if current tab has references.
*/
bool PropertyProxy::hasReference() const
{
  if(_currentTab) {
    return _currentTab->hasReference();
  } else {
    return false;
  }
}

/*!
  Returns the number of references to the current tab
*/
int PropertyProxy::referenceCount() const
{
  if(_currentTab) {
    return _currentTab->referenceCount();
  } else {
    return 0;
  }
}

void PropertyProxy::removeTab(uint tab, PropertyItem * item)
{
  if(_currentCategory) {
    ExpandTabWidget * w;
    if(isActive()) {
      w=static_cast<ExpandTabWidget *>(PropertyEditor::instance()->widget(_currentCategory->caption()));
    } else {
      w=0;
    }
    _currentCategory->removeTab(tab, item, w);
    if(_currentCategory->isEmpty()) {
      _categories.remove(_currentCategory->tag());
      if(isActive()) PropertyEditor::instance()->removeCategory(_currentCategory->caption());
      delete _currentCategory;
      _currentCategory=0;
    }
  }
}

} // namespace QGpGuiTools
