

#include "cellkeyframeselection.h"

// Tnz6 includes
#include "menubarcommandids.h"
#include "cellkeyframedata.h"

// TnzLib includes
#include "toonz/txsheethandle.h"
#include "toonz/txsheet.h"
#include "toonz/tstageobject.h"

// TnzCore includes
#include "tundo.h"

// Qt includes
#include <QApplication>
#include <QClipboard>

// C++ includes
#include <memory>

//=============================================================================
//  TCellKeyframeSelection
//-----------------------------------------------------------------------------

TCellKeyframeSelection::TCellKeyframeSelection(
    TCellSelection *cellSelection, TKeyframeSelection *keyframeSelection)
    : m_cellSelection(cellSelection)
    , m_keyframeSelection(keyframeSelection)
    , m_xsheetHandle(nullptr) {}

//-----------------------------------------------------------------------------

void TCellKeyframeSelection::enableCommands() {
  enableCommand(this, MI_Copy, &TCellKeyframeSelection::copyCellsKeyframes);
  enableCommand(this, MI_Paste, &TCellKeyframeSelection::pasteCellsKeyframes);
  enableCommand(this, MI_Cut, &TCellKeyframeSelection::cutCellsKeyframes);
  enableCommand(this, MI_Clear, &TCellKeyframeSelection::deleteCellsKeyframes);
}

//-----------------------------------------------------------------------------

bool TCellKeyframeSelection::isEmpty() const {
  return m_keyframeSelection->isEmpty() && m_cellSelection->isEmpty();
}

//-----------------------------------------------------------------------------

void TCellKeyframeSelection::copyCellsKeyframes() {
  auto data    = std::make_unique<TCellKeyframeData>();
  bool hasData = false;

  int r0, c0, r1, c1;
  m_cellSelection->getSelectedCells(r0, c0, r1, c1);
  if (!m_cellSelection->isEmpty()) {
    int colCount = c1 - c0 + 1;
    int rowCount = r1 - r0 + 1;
    if (colCount > 0 && rowCount > 0) {
      TXsheet *xsh   = m_xsheetHandle->getXsheet();
      auto *cellData = new TCellData();
      cellData->setCells(xsh, r0, c0, r1, c1);
      data->setCellData(cellData);
      hasData = true;
    }
  }

  if (!m_keyframeSelection->isEmpty()) {
    TXsheet *xsh       = m_xsheetHandle->getXsheet();
    auto *keyframeData = new TKeyframeData();
    TKeyframeData::Position startPos(r0, c0);
    keyframeData->setKeyframes(m_keyframeSelection->getSelection(), xsh,
                               startPos);
    data->setKeyframeData(keyframeData);
    hasData = true;
  }

  if (hasData) {
    QApplication::clipboard()->setMimeData(data.release(),
                                           QClipboard::Clipboard);
  }
}

//-----------------------------------------------------------------------------

void TCellKeyframeSelection::pasteCellsKeyframes() {
  m_cellSelection->pasteCells();
}

//-----------------------------------------------------------------------------

void TCellKeyframeSelection::deleteCellsKeyframes() {
  TUndoManager::manager()->beginBlock();
  // clear cells without shifting
  // TODO: behavior of deleting cell+keyframe should also follow the preference
  // option.
  m_cellSelection->deleteCells(false);  // clear without shifting
  m_keyframeSelection->deleteKeyframes();
  TUndoManager::manager()->endBlock();
}

//-----------------------------------------------------------------------------

void TCellKeyframeSelection::cutCellsKeyframes() {
  copyCellsKeyframes();

  TUndoManager::manager()->beginBlock();
  int r0, c0, r1, c1;
  m_cellSelection->getSelectedCells(r0, c0, r1, c1);
  m_cellSelection->cutCells(true);
  m_keyframeSelection->deleteKeyframesWithShift(r0, r1, c0, c1);
  TUndoManager::manager()->endBlock();
}

//-----------------------------------------------------------------------------

void TCellKeyframeSelection::selectCellsKeyframes(int r0, int c0, int r1,
                                                  int c1) {
  m_cellSelection->selectCells(r0, c0, r1, c1);
  TXsheet *xsh = m_xsheetHandle->getXsheet();
  if (r1 < r0) std::swap(r0, r1);
  if (c1 < c0) std::swap(c0, c1);
  m_keyframeSelection->clear();
  for (int c = c0; c <= c1; ++c) {
    TStageObjectId id =
        (c < 0) ? TStageObjectId::CameraId(xsh->getCameraColumnIndex())
                : TStageObjectId::ColumnId(c);
    TStageObject *stObj = xsh->getStageObject(id);
    for (int r = r0; r <= r1; ++r) {
      if (stObj->isKeyframe(r)) m_keyframeSelection->select(r, c);
    }
  }
}

//-----------------------------------------------------------------------------

void TCellKeyframeSelection::selectCellKeyframe(int row, int col) {
  m_cellSelection->selectCell(row, col);
  TXsheet *xsh = m_xsheetHandle->getXsheet();
  TStageObjectId id =
      (col < 0) ? TStageObjectId::CameraId(xsh->getCameraColumnIndex())
                : TStageObjectId::ColumnId(col);
  TStageObject *stObj = xsh->getStageObject(id);
  m_keyframeSelection->clear();
  if (stObj->isKeyframe(row)) m_keyframeSelection->select(row, col);
}

//-----------------------------------------------------------------------------

void TCellKeyframeSelection::selectNone() {
  m_cellSelection->selectNone();
  m_keyframeSelection->selectNone();
}
