/*
 * Copyright (C) 2005-2020 Centre National d'Etudes Spatiales (CNES)
 *
 * This file is part of Orfeo Toolbox
 *
 *     https://www.orfeo-toolbox.org/
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "mvdHistogramController.h"


/*****************************************************************************/
/* INCLUDE SECTION                                                           */

//
// Qt includes (sorted by alphabetic order)
//// Must be included before system/custom includes.

//
// System includes (sorted by alphabetic order)

//
// ITK includes (sorted by alphabetic order)

//
// OTB includes (sorted by alphabetic order)

//
// Monteverdi includes (sorted by alphabetic order)
#include "mvdVectorImageModel.h"
#include "mvdHistogramWidget.h"

namespace mvd
{
/*
  TRANSLATOR mvd::HistogramController

  Necessary for lupdate to be aware of C++ namespaces.

  Context comment for translator.
*/


/*****************************************************************************/
/* CLASS IMPLEMENTATION SECTION                                              */

/*******************************************************************************/
HistogramController::HistogramController(HistogramWidget* widget, QObject* p) : AbstractModelController(widget, p)
{
}

/*******************************************************************************/
HistogramController::~HistogramController()
{
}

/*******************************************************************************/
void HistogramController::Connect(AbstractModel*)
{
  // HistogramWidget* widget = GetWidget< HistogramWidget >();

  //
  // Connect GUI to controller.

  //
  // Connect controller to model.
}

/*******************************************************************************/
void HistogramController::Disconnect(AbstractModel*)
{
  // HistogramWidget* widget = GetWidget< HistogramWidget >();

  //
  // Disconnect controller to model.

  //
  // Disconnect GUI from controller.
}

/*******************************************************************************/
void HistogramController::ClearWidget()
{
  assert(GetWidget() == GetWidget<HistogramWidget>());
  HistogramWidget* widget = GetWidget<HistogramWidget>();
  assert(widget != NULL);

  widget->Clear();
}

/*******************************************************************************/
void HistogramController::virtual_ResetWidget(bool)
{
  ResetWidget(RGBW_CHANNEL_ALL);
}

/*******************************************************************************/
void HistogramController::ResetWidget(RgbwChannel channel)
{
  assert(GetModel() == GetModel<VectorImageModel>());
  VectorImageModel* imageModel = GetModel<VectorImageModel>();
  assert(imageModel != NULL);

  HistogramModel* model = imageModel->GetHistogramModel();
  assert(model != NULL);

  if (!model->IsValid())
    return;

  assert(GetWidget() == GetWidget<HistogramWidget>());
  HistogramWidget* widget = GetWidget<HistogramWidget>();
  assert(widget != NULL);

  CountType begin = 0;
  CountType end   = 0;

  if (!RgbwBounds(begin, end, channel))
    return;

  const VectorImageSettings& settings = imageModel->GetSettings();

  widget->SetGrayscaleActivated(settings.IsGrayscaleActivated());

  assert(std::numeric_limits<double>::has_quiet_NaN);

  for (CountType i = begin; i < end; ++i)
  {
    RgbwChannel chan = static_cast<RgbwChannel>(i);

    VectorImageSettings::ChannelVector::value_type band = settings.GetRgbwChannel(chan);

    size_t size = model->GetDataCount(band);

    double* x = new double[size];
    double* y = new double[size];

    double xMin = std::numeric_limits<double>::quiet_NaN();
    double yMin = std::numeric_limits<double>::quiet_NaN();
    double xMax = std::numeric_limits<double>::quiet_NaN();
    double yMax = std::numeric_limits<double>::quiet_NaN();

    model->GetData(band, x, y, xMin, xMax, yMin, yMax);

    widget->SetData(chan, x, y, size, xMin, yMin, xMax, yMax);

    widget->SetPrecision(HistogramModel::GetEpsilon());
    widget->SetLowMarker(chan, settings.GetLowIntensity(chan));
    widget->SetHighMarker(chan, settings.GetHighIntensity(chan));

    delete[] x;
    x = NULL;

    delete[] y;
    y = NULL;
  }

  widget->RefreshScale(true);

  widget->Replot();
}

/*****************************************************************************/
/* SLOTS                                                                     */
/*****************************************************************************/
void HistogramController::OnRgbChannelIndexChanged(RgbwChannel channel, int)
{
  /*
  qDebug()
    << this
    << "::OnRgbChannelIndexChanged("
    << RGBW_CHANNEL_NAMES[ channel ] << ", " << band <<
    ")";
  */

  ResetWidget(channel);
}

/*****************************************************************************/
void HistogramController::OnGrayChannelIndexChanged(int)
{
  /*
  qDebug()
    << this
    << "::OnGrayChannelIndexChanged(" << band << ")";
  */

  ResetWidget(RGBW_CHANNEL_WHITE);
}

/*****************************************************************************/
void HistogramController::OnGrayscaleActivated(bool activated)
{
  /*
  qDebug()
    << this
    << "::OnGrayscaleActivated(" << activated << ")";
  */

  assert(GetWidget() == GetWidget<HistogramWidget>());
  HistogramWidget* widget = GetWidget<HistogramWidget>();
  assert(widget != NULL);

  widget->SetGrayscaleActivated(activated);

  widget->RefreshScale(true);
  widget->Replot();
}

/*****************************************************************************/
void HistogramController::OnLowIntensityChanged(RgbwChannel channel, double value, bool refresh)
{
  assert(GetWidget() == GetWidget<HistogramWidget>());
  HistogramWidget* widget = GetWidget<HistogramWidget>();
  assert(widget != NULL);

  widget->SetLowMarker(channel, value);

  if (refresh)
    widget->Replot();
}

/*****************************************************************************/
void HistogramController::OnHighIntensityChanged(RgbwChannel channel, double value, bool refresh)
{
  assert(GetWidget() == GetWidget<HistogramWidget>());
  HistogramWidget* widget = GetWidget<HistogramWidget>();
  assert(widget != NULL);

  widget->SetHighMarker(channel, value);

  if (refresh)
    widget->Replot();
}

/*****************************************************************************/
void HistogramController::OnHistogramRefreshed()
{
  ResetWidget(RGBW_CHANNEL_ALL);
}

/*****************************************************************************/

} // end namespace 'mvd'
