//=========================================================================
//  Copyright (c) Kitware, Inc.
//  All rights reserved.
//  See LICENSE.txt for details.
//
//  This software is distributed WITHOUT ANY WARRANTY; without even
//  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
//  PURPOSE.  See the above copyright notice for more information.
//=========================================================================
#include "pqCMBPostProcessingModeBehavior.h"

// Client side
#include "pqApplicationCore.h"
#include "pqCoreUtilities.h"
#include "pqInterfaceTracker.h"
#include "pqOutputPort.h"
#include "pqPVApplicationCore.h"
#include "pqParaViewMenuBuilders.h"
#include "smtk/extension/paraview/appcomponents/pqSMTKBehavior.h"

// Server side
#include "vtkLogger.h"

// Qt
#include <QAction>
#include <QDir>
#include <QMainWindow>
#include <QMenu>
#include <QMenuBar>
#include <QMetaObject>
#include <QTimer>
#include <QToolBar>
#include <QWidget>

// Qt generated UI
#include "ui_pqCMBPostProcessingModeBehavior.h"

#include <iostream>
#include <vector>

static pqCMBPostProcessingModeBehavior* s_postMode = nullptr;

class pqCMBPostProcessingModeBehavior::pqInternal
{
public:
  Ui::pqCMBPostProcessingModeBehavior Actions;
  QAction* ModeAction;
  QWidget ActionsOwner;
};

pqCMBPostProcessingModeBehavior::pqCMBPostProcessingModeBehavior(QObject* parent)
  : Superclass(parent)
{
  m_p = new pqInternal;
  m_p->Actions.setupUi(&m_p->ActionsOwner);

  m_p->ModeAction = m_p->Actions.actionPostProcessingMode;

  if (!s_postMode)
  {
    s_postMode = this;
  }

  // By default, the button is off. Register them in this state.
  this->addAction(m_p->ModeAction);
  this->setExclusive(false);

  QObject::connect(this, SIGNAL(triggered(QAction*)), this, SLOT(switchModes(QAction*)));
  QTimer::singleShot(0, this, SLOT(prepare()));
}

pqCMBPostProcessingModeBehavior::~pqCMBPostProcessingModeBehavior()
{
  if (s_postMode == this)
  {
    s_postMode = nullptr;
  }

  delete m_p;
}

pqCMBPostProcessingModeBehavior* pqCMBPostProcessingModeBehavior::instance()
{
  return s_postMode;
}

void pqCMBPostProcessingModeBehavior::prepare()
{
  auto* behavior = pqSMTKBehavior::instance();
  if (behavior)
  {
    // This ugly loop to SMTK and back lets ParaView components
    // in SMTK check the post-processing state:
    // 1. Clicking the toolbar button signals the pqSMTKBehavior to change state.
    QObject::connect(
      this, SIGNAL(togglePostProcessingMode(bool)), behavior, SLOT(setPostProcessingMode(bool)));
    // 2. When the pqSMTKBehavior changes state, tell the application to switch modes.
    QObject::connect(
      behavior,
      SIGNAL(postProcessingModeChanged(bool)),
      pqCoreUtilities::mainWidget(),
      SLOT(togglePostProcessingMode(bool)));
  }
  else
  {
    vtkVLogF(
      vtkLogger::VERBOSITY_WARNING,
      "SMTK plugin not loaded; post-processing button will not work.");
  }
}

void pqCMBPostProcessingModeBehavior::switchModes(QAction* a)
{
  Q_EMIT togglePostProcessingMode(a->isChecked());
}
