//
// This file is part of MorphoGraphX - http://www.MorphoGraphX.org
// Copyright (C) 2012-2015 Richard S. Smith and collaborators.
//
// If you use MorphoGraphX in your work, please cite:
//   http://dx.doi.org/10.7554/eLife.05864
//
// MorphoGraphX is free software, and is licensed under under the terms of the 
// GNU General (GPL) Public License version 2.0, http://www.gnu.org/licenses.
// 
#include "PathEditorDlg.hpp"

#include "MorphoViewer.hpp"
#include <MGXViewer/keyFrameInterpolator.h>

using qglviewer::Frame;
using qglviewer::KeyFrameInterpolator;

PathEditorModel::PathEditorModel(MGXCamera* c, QObject* parent)
  : QAbstractItemModel(parent), camera(c) {}

int PathEditorModel::rowCount(const QModelIndex& parent) const
{
  if(!parent.isValid()) {
    return 12;
  } else {
    if(isPath(parent)) {
      KeyFrameInterpolator* fi = path(parent);
      if(fi)
        return fi->numberOfKeyFrames();
      else
        return 0;
    }
  }
  return 0;
}

QVariant PathEditorModel::data(const QModelIndex& index, int role) const
{
  if(index.isValid()) {
    if(isPath(index)) {
      if(role == Qt::DisplayRole) {
        return QString("Path %1").arg(pathId(index));
      }
    } else {
      if(role == Qt::DisplayRole) {
        return QString("Keyframe %1").arg(keyframeId(index) + 1);
      }
    }
  }
  return QVariant();
}

/*
 * QMap<int, QVariant> PathEditorModel::itemData(const QModelIndex & index) const
 *{
 *}
 */

QVariant PathEditorModel::headerData(int section, Qt::Orientation orientation, int ) const
{
  if(orientation == Qt::Horizontal) {
    if(section == 0)
      return "Paths";
  }
  return QVariant();
}

Qt::ItemFlags PathEditorModel::flags(const QModelIndex& ) const
{
  return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}

/*
 * bool PathEditorModel::setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole)
 *{
 *}
 */

/*
 * bool PathEditorModel::setItemData(const QModelIndex& index, const QMap<int, QVariant>& roles)
 *{
 *}
 */

QModelIndex PathEditorModel::index(int row, int column, const QModelIndex& parent) const
{
  if(column != 0)
    return QModelIndex();
  if(!parent.isValid()) {
    if(row >= 0 and row < 12)
      return createIndex(row, column, quint32(row + 1) << 24);
  } else {
    quint32 idx = pathId(parent);
    KeyFrameInterpolator* pi = camera->keyFrameInterpolator(idx);
    if(pi) {
      if(row >= 0 and row < pi->numberOfKeyFrames())
        return createIndex(row, column, (idx << 24) + quint32(row) + 1);
    }
  }
  return QModelIndex();
}

QModelIndex PathEditorModel::parent(const QModelIndex& index) const
{
  if(isKeyframe(index))
    return this->index(int(pathId(index) - 1), 0);
  return QModelIndex();
}

bool PathEditorModel::isPath(const QModelIndex& idx) const
{
  if(idx.isValid()) {
    quint32 id = quint32(idx.internalId());
    return (id & ((1 << 24) - 1)) == 0;
  }
  return false;
}

bool PathEditorModel::isKeyframe(const QModelIndex& idx) const
{
  if(idx.isValid()) {
    quint32 id = quint32(idx.internalId());
    return (id & ((1 << 24) - 1)) != 0;
  }
  return false;
}

quint32 PathEditorModel::pathId(const QModelIndex& idx) const
{
  if(idx.isValid()) {
    return quint32(idx.internalId()) >> 24;
  }
  return quint32(0);
}

quint32 PathEditorModel::keyframeId(const QModelIndex& idx) const
{
  if(idx.isValid()) {
    return (quint32(idx.internalId()) & ((1 << 24) - 1)) - 1;
  }
  return quint32(-1);
}

KeyFrameInterpolator* PathEditorModel::path(const QModelIndex& idx) const
{
  if(idx.isValid()) {
    return camera->keyFrameInterpolator(pathId(idx));
  }
  return 0;
}

void PathEditorModel::moveTo(const QModelIndex& idx) const
{
  KeyFrameInterpolator* fi = path(idx);
  if(fi) {
    Frame f = fi->keyFrame(keyframeId(idx));
    camera->interpolateTo(f, 1);
  }
}

PathEditorDlg::PathEditorDlg(QWidget* parent, MGXCamera* c)
  : QDialog(parent)
  , camera(c)
{
  setAttribute(Qt::WA_DeleteOnClose, true);
  ui.setupUi(this);
  ui.buttonBox->addButton("Add KeyFrame", QDialogButtonBox::ActionRole);
  model = new PathEditorModel(camera, this);
  ui.pathsView->setModel(model);
}

void PathEditorDlg::on_buttonBox_clicked(QAbstractButton* ) {
}

void PathEditorDlg::on_pathsView_clicked(const QModelIndex& ) {
}

void PathEditorDlg::on_pathsView_doubleClicked(const QModelIndex& idx)
{
  if(model->isKeyframe(idx))
    model->moveTo(idx);
}
