/* poppler-optcontent.cc: qt interface to poppler
 *
 * Copyright (C) 2007, Brad Hards <bradh@kde.org>
 * Copyright (C) 2008, 2014, Pino Toscano <pino@kde.org>
 * Copyright (C) 2008, Carlos Garcia Campos <carlosgc@gnome.org>
 * Copyright (C) 2015-2019, Albert Astals Cid <aacid@kde.org>
 * Copyright (C) 2017, Hubert Figuière <hub@figuiere.net>
 * Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, <info@kdab.com>. Work sponsored by the LiMux project of the city of Munich
 * Copyright (C) 2018 Adam Reichold <adam.reichold@t-online.de>
 * Copyright (C) 2019 Oliver Sander <oliver.sander@tu-dresden.de>
 *
 * This program 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, or (at your option)
 * any later version.
 *
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include "poppler-optcontent.h"

#include "poppler-optcontent-private.h"

#include "poppler-private.h"
#include "poppler-link-private.h"

#include <QtCore/QDebug>
#include <QtCore/QtAlgorithms>

#include "poppler/OptionalContent.h"
#include "poppler/Link.h"

namespace Poppler
{

  RadioButtonGroup::RadioButtonGroup( OptContentModelPrivate *ocModel, Array *rbarray )
  {
    itemsInGroup.reserve(rbarray->getLength());
    for (int i = 0; i < rbarray->getLength(); ++i) {
      const Object &ref = rbarray->getNF( i );
      if ( ! ref.isRef() ) {
	qDebug() << "expected ref, but got:" << ref.getType();
      }
      OptContentItem *item = ocModel->itemFromRef( QString::number(ref.getRefNum() ) );
      itemsInGroup.append( item );
    }
    for (int i = 0; i < itemsInGroup.size(); ++i) {
      OptContentItem *item = itemsInGroup.at(i);
      item->appendRBGroup( this );
    }
  }

  RadioButtonGroup::~RadioButtonGroup()
  {
  }

  QSet<OptContentItem *> RadioButtonGroup::setItemOn( OptContentItem *itemToSetOn )
  {
    QSet<OptContentItem *> changedItems;
    for (int i = 0; i < itemsInGroup.size(); ++i) {
      OptContentItem *thisItem = itemsInGroup.at(i);
      if (thisItem != itemToSetOn) {
        QSet<OptContentItem *> newChangedItems;
        thisItem->setState(OptContentItem::Off, false /*obeyRadioGroups*/, newChangedItems);
        changedItems += newChangedItems;
      }
    }
    return changedItems;
  }



  OptContentItem::OptContentItem( OptionalContentGroup *group )
  {
    m_group = group;
    m_parent = nullptr;
    m_name = UnicodeParsedString( group->getName() );
    if ( group->getState() == OptionalContentGroup::On ) {
      m_state = OptContentItem::On;
    } else {
      m_state = OptContentItem::Off;
    }
    m_stateBackup = m_state;
    m_enabled = true;
  }

  OptContentItem::OptContentItem( const QString &label )
  {
    m_parent = nullptr;
    m_name = label;
    m_group = nullptr;
    m_state = OptContentItem::HeadingOnly;
    m_stateBackup = m_state;
    m_enabled = true;
  }

  OptContentItem::OptContentItem() :
    m_parent( nullptr ), m_enabled(true)
  {
  }

  OptContentItem::~OptContentItem()
  {
  }

  void OptContentItem::appendRBGroup( RadioButtonGroup *rbgroup )
  {
    m_rbGroups.append( rbgroup );
  }


  void OptContentItem::setState(ItemState state, bool obeyRadioGroups, QSet<OptContentItem *> &changedItems)
  {
    if (state == m_state)
        return;

    m_state = state;
    m_stateBackup = m_state;
    changedItems.insert(this);
    QSet<OptContentItem *> empty;
    Q_FOREACH (OptContentItem *child, m_children) {
      ItemState oldState = child->m_stateBackup;
      child->setState(state == OptContentItem::On ? child->m_stateBackup : OptContentItem::Off, true /*obeyRadioGroups*/, empty);
      child->m_enabled = state == OptContentItem::On;
      child->m_stateBackup = oldState;
    }
    if (!m_group) {
      return;
    }
    if ( state == OptContentItem::On ) {
      m_group->setState( OptionalContentGroup::On );
      if (obeyRadioGroups) {
	for (int i = 0; i < m_rbGroups.size(); ++i) {
	  RadioButtonGroup *rbgroup = m_rbGroups.at(i);
	  changedItems += rbgroup->setItemOn( this );
	}
      }
    } else if ( state == OptContentItem::Off ) {
      m_group->setState( OptionalContentGroup::Off );
    }
  }

  void OptContentItem::addChild( OptContentItem *child )
  {
    m_children += child;
    child->setParent( this );
  }

  QSet<OptContentItem*> OptContentItem::recurseListChildren(bool includeMe) const
  {
    QSet<OptContentItem*> ret;
    if (includeMe) {
      ret.insert(const_cast<OptContentItem*>(this));
    }
    Q_FOREACH (OptContentItem *child, m_children) {
      ret += child->recurseListChildren(true);
    }
    return ret;
  }

  OptContentModelPrivate::OptContentModelPrivate( OptContentModel *qq, OCGs *optContent )
    : q(qq)
  {
    m_rootNode = new OptContentItem();
    const auto &ocgs = optContent->getOCGs();

    for (const auto& ocg : ocgs) {
      OptContentItem *node = new OptContentItem( ocg.second.get() );
      m_optContentItems.insert( QString::number( ocg.first.num ), node );
    }

    if ( optContent->getOrderArray() == nullptr ) {
      // no Order array, so drop them all at the top level
      QMapIterator<QString, OptContentItem*> i(m_optContentItems);
      while ( i.hasNext() ) {
	i.next();
	addChild( m_rootNode, i.value() );
      }
    } else {
      parseOrderArray( m_rootNode, optContent->getOrderArray() );
    }

    parseRBGroupsArray( optContent->getRBGroupsArray() );
  }

  OptContentModelPrivate::~OptContentModelPrivate()
  {
    qDeleteAll( m_optContentItems );
    qDeleteAll( m_rbgroups );
    qDeleteAll( m_headerOptContentItems );
    delete m_rootNode;
  }

  void OptContentModelPrivate::parseOrderArray( OptContentItem *parentNode, Array *orderArray )
  {
    OptContentItem *lastItem = parentNode;
    for (int i = 0; i < orderArray->getLength(); ++i) {
      Object orderItem = orderArray->get(i);
      if ( orderItem.isDict() ) {
	const Object &item = orderArray->getNF(i);
	if (item.isRef() ) {
          OptContentItem *ocItem = m_optContentItems.value(QString::number(item.getRefNum()));
	  if (ocItem) {
	    addChild( parentNode, ocItem );
	    lastItem = ocItem;
	  } else {
            qDebug() << "could not find group for object" << item.getRefNum();
	  }
	}
      } else if ( (orderItem.isArray()) && (orderItem.arrayGetLength() > 0) ) {
	parseOrderArray(lastItem, orderItem.getArray());
      } else if ( orderItem.isString() ) {
	const GooString *label = orderItem.getString();
	OptContentItem *header = new OptContentItem ( UnicodeParsedString ( label ) );
	m_headerOptContentItems.append( header );
	addChild( parentNode, header );
	parentNode = header;
	lastItem = header;
      } else {
	qDebug() << "something unexpected";
      }	
    }
  }

  void OptContentModelPrivate::parseRBGroupsArray( Array *rBGroupArray )
  {
    if (! rBGroupArray) {
      return;
    }
    // This is an array of array(s)
    for (int i = 0; i < rBGroupArray->getLength(); ++i) {
      Object rbObj = rBGroupArray->get(i);
      if ( ! rbObj.isArray() ) {
	qDebug() << "expected inner array, got:" << rbObj.getType();
	return;
      }
      Array *rbarray = rbObj.getArray();
      RadioButtonGroup *rbg = new RadioButtonGroup( this, rbarray );
      m_rbgroups.append( rbg );
    }
  }

  OptContentModel::OptContentModel( OCGs *optContent, QObject *parent)
    : QAbstractItemModel(parent)
  {
    d = new OptContentModelPrivate( this, optContent );
  }

  OptContentModel::~OptContentModel()
  {
    delete d;
  }

  void OptContentModelPrivate::setRootNode(OptContentItem *node)
  {
    q->beginResetModel();
    delete m_rootNode;
    m_rootNode = node;
    q->endResetModel();
  }

  QModelIndex OptContentModel::index(int row, int column, const QModelIndex &parent) const
  {
    if (row < 0 || column != 0) {
      return QModelIndex();
    }

    OptContentItem *parentNode = d->nodeFromIndex( parent );
    if (row < parentNode->childList().count()) {
      return createIndex(row, column, parentNode->childList().at(row));
    }
    return QModelIndex();
  }

  QModelIndex OptContentModel::parent(const QModelIndex &child) const
  {
    OptContentItem *childNode = d->nodeFromIndex( child );
    if (!childNode) {
      return QModelIndex();
    }
    return d->indexFromItem(childNode->parent(), child.column());
  }

  QModelIndex OptContentModelPrivate::indexFromItem(OptContentItem *node, int column) const
  {
    if (!node) {
      return QModelIndex();
    }
    OptContentItem *parentNode = node->parent();
    if (!parentNode) {
      return QModelIndex();
    }
    const int row = parentNode->childList().indexOf(node);
    return q->createIndex(row, column, node);
  }
 
  int OptContentModel::rowCount(const QModelIndex &parent) const
  {
    OptContentItem *parentNode = d->nodeFromIndex( parent );
    if (!parentNode) {
      return 0;
    } else {
      return parentNode->childList().count();
    }
  }

  int OptContentModel::columnCount(const QModelIndex &parent) const
  {
    return 1;
  }


  QVariant OptContentModel::data(const QModelIndex &index, int role) const
  {
    OptContentItem *node = d->nodeFromIndex(index, true);
    if (!node) {
      return QVariant();
    }

    switch (role) {
      case Qt::DisplayRole:
        return node->name();
        break;
      case Qt::EditRole:
        if (node->state() == OptContentItem::On) {
          return true;
        } else if (node->state() == OptContentItem::Off) {
          return false;
        }
        break;
      case Qt::CheckStateRole:
        if (node->state() == OptContentItem::On) {
          return Qt::Checked;
        } else if (node->state() == OptContentItem::Off) {
          return Qt::Unchecked;
        }
        break;
    }

    return QVariant();
  }

  bool OptContentModel::setData ( const QModelIndex & index, const QVariant & value, int role )
  {
    OptContentItem *node = d->nodeFromIndex(index, true);
    if (!node) {
      return false;
    }

    switch (role) {
      case Qt::CheckStateRole:
      {
        const bool newvalue = value.toBool();
        QSet<OptContentItem *> changedItems;
        node->setState(newvalue ? OptContentItem::On : OptContentItem::Off, true /*obeyRadioGroups*/, changedItems);

        if (!changedItems.isEmpty()) {
          changedItems += node->recurseListChildren(false);
          QModelIndexList indexes;
          Q_FOREACH (OptContentItem *item, changedItems) {
            indexes.append(d->indexFromItem(item, 0));
          }
          std::stable_sort(indexes.begin(), indexes.end());
          Q_FOREACH (const QModelIndex &changedIndex, indexes) {
            emit dataChanged(changedIndex, changedIndex);
          }
          return true;
        }
        break;
      }
    }

    return false;
  }

  Qt::ItemFlags OptContentModel::flags ( const QModelIndex & index ) const
  {
    OptContentItem *node = d->nodeFromIndex(index);
    Qt::ItemFlags itemFlags = Qt::ItemIsSelectable | Qt::ItemIsUserCheckable;
    if (node->isEnabled()) {
      itemFlags |= Qt::ItemIsEnabled;
    }
    return itemFlags;
  }

  QVariant OptContentModel::headerData( int section, Qt::Orientation orientation, int role ) const
  {
    return QAbstractItemModel::headerData( section, orientation, role );
  }

  void OptContentModel::applyLink( LinkOCGState *link )
  {
    ::LinkOCGState *popplerLinkOCGState = static_cast<LinkOCGStatePrivate*>(link->d_ptr)->popplerLinkOCGState;

    QSet<OptContentItem *> changedItems;

    const std::vector<::LinkOCGState::StateList*> *statesList = popplerLinkOCGState->getStateList();
    for (std::size_t i = 0; i < statesList->size(); ++i) {
        ::LinkOCGState::StateList *stateList = (*statesList)[i];

        std::vector<Ref*> *refsList = stateList->list;
        for (std::size_t j = 0; j < refsList->size(); ++j) {
            Ref *ref = (*refsList)[j];
            OptContentItem *item = d->itemFromRef(QString::number(ref->num));

            if (stateList->st == ::LinkOCGState::On) {
              item->setState(OptContentItem::On, popplerLinkOCGState->getPreserveRB(), changedItems);
            } else if (stateList->st == ::LinkOCGState::Off) {
              item->setState(OptContentItem::Off, popplerLinkOCGState->getPreserveRB(), changedItems);
            } else {
              OptContentItem::ItemState newState = item->state() == OptContentItem::On ? OptContentItem::Off : OptContentItem::On;
              item->setState(newState, popplerLinkOCGState->getPreserveRB(), changedItems);
            }
        }
    }

    if (!changedItems.isEmpty()) {
      QSet<OptContentItem *> aux;
      Q_FOREACH (OptContentItem *item, aux) {
        changedItems += item->recurseListChildren(false);
      }

      QModelIndexList indexes;
      Q_FOREACH (OptContentItem *item, changedItems) {
        indexes.append(d->indexFromItem(item, 0));
      }
      std::stable_sort(indexes.begin(), indexes.end());
      Q_FOREACH (const QModelIndex &changedIndex, indexes) {
        emit dataChanged(changedIndex, changedIndex);
      }
    }
  }

  void OptContentModelPrivate::addChild( OptContentItem *parent, OptContentItem *child )
  {
    parent->addChild( child );
  }

  OptContentItem* OptContentModelPrivate::itemFromRef( const QString &ref ) const
  {
    return m_optContentItems.value(ref);
  }

  OptContentItem* OptContentModelPrivate::nodeFromIndex(const QModelIndex &index, bool canBeNull) const
  {
    if (index.isValid()) {
      return static_cast<OptContentItem *>(index.internalPointer());
    } else {
      return canBeNull ? nullptr : m_rootNode;
    }
  }
}

