
/*******************************************************************************
 * Copyright (c) 2018 Olivier Langella <olivier.langella@u-psud.fr>.
 *
 * This file is part of i2MassChroQ.
 *
 *     i2MassChroQ 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 3 of the License, or
 *     (at your option) any later version.
 *
 *     i2MassChroQ 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 i2MassChroQ.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Contributors:
 *     Olivier Langella <olivier.langella@u-psud.fr> - initial API and
 *implementation
 ******************************************************************************/

#include <QDebug>
#include <QFuture>
#include <QtConcurrent/QtConcurrent>

#include "msidlistworkerstatus.h"
#include <pappsomspp/core/pappsoexception.h>
#include <pappsomspp/core/exception/exceptionnotfound.h>
#include <gui/lists/ms_identification_run_list_view/msidentificationtablemodel.h>
#include <gui/lists/ms_identification_run_list_view/msidentificationlistwindow.h>

bool
MsIdentificationTableMsRunStatisticsHandler::shouldStop()
{
  QMutexLocker locker(&m_mutex);
  return m_stopRequired;
}

void
MsIdentificationTableMsRunStatisticsHandler::requireStop(bool stop)
{
  QMutexLocker locker(&m_mutex);
  m_stopRequired = stop;
}


MsIdListWorkerStatus::MsIdListWorkerStatus()
{
}

MsIdListWorkerStatus::~MsIdListWorkerStatus()
{
  qDebug();
  if(mpa_currentHandler != nullptr)
    {
      mpa_currentHandler->requireStop(true);
      m_computingThread.waitForFinished();
    }
  qDebug();
}


void
MsIdListWorkerStatus::stopThreads()
{
  qDebug();
  if(mpa_currentHandler != nullptr)
    {
      mpa_currentHandler->requireStop(true);
      m_computingThread.waitForFinished();
    }
  qDebug();
}

WorkerStatus
MsIdListWorkerStatus::getStatus(
  IdentificationDataSourceSp identificationDataSource)
{
  if(std::find(m_identificationReady.begin(),
               m_identificationReady.end(),
               identificationDataSource.get()) != m_identificationReady.end())
    {
      return WorkerStatus::Ready;
    }
  if(std::find(m_identificationError.begin(),
               m_identificationError.end(),
               identificationDataSource.get()) != m_identificationError.end())
    {
      return WorkerStatus::Error;
    }

  if(std::find(m_identificationFileNotFound.begin(),
               m_identificationFileNotFound.end(),
               identificationDataSource.get()) !=
     m_identificationFileNotFound.end())
    {
      return WorkerStatus::FileNotFound;
    }

  if((m_computingThread.isRunning()) &&
     (m_runningData == identificationDataSource.get()))
    {
      return WorkerStatus::Running;
    }

  // Check if idDataSource is in the deque
  if(std::find(m_waitingComputing.begin(),
               m_waitingComputing.end(),
               identificationDataSource) != m_waitingComputing.end())
    {
      if(m_computingThread.isRunning())
        {
          return WorkerStatus::Waiting;
        }
      else
        {
          if(identificationDataSource.get() == m_waitingComputing.front().get())
            {
              m_runningData = identificationDataSource.get();
              m_waitingComputing.pop_front();
              m_computingThread =
                QtConcurrent::run(&MsIdListWorkerStatus::doComputeMsNumber,
                                  this,
                                  identificationDataSource);
              return WorkerStatus::Running;
            }
          else
            {
              return WorkerStatus::Waiting;
            }
        }
    }
  else
    {
    }


  if(m_waitingComputing.size() >= 5)
    {
      return WorkerStatus::NotReady;
    }
  else
    {
      m_waitingComputing.push_back(identificationDataSource);
      return WorkerStatus::Waiting;
    }
}


void
MsIdListWorkerStatus::doComputeMsNumber(
  IdentificationDataSourceSp identificationDataSource)
{
  qDebug();
  pappso::MsRunReaderSPtr msrun_reader_sp =
    identificationDataSource->getMsRunSp().get()->getMsRunReaderSPtr();
  if(msrun_reader_sp.get() != nullptr)
    {
      QVariant msrun_var =
        identificationDataSource->getMsRunSp()->getMsRunStatistics(
          MsRunStatistics::total_spectra);
      if(!msrun_var.isNull())
        {
          // no need to compute : this is already there
          m_identificationReady.push_back(identificationDataSource.get());
        }
    }

  if(identificationDataSource->getMsRunSp()->findMsRunFile())
    {
      try
        {
          msrun_reader_sp =
            identificationDataSource->getMsRunSp().get()->getMsRunReaderSPtr();

          if(msrun_reader_sp.get() != nullptr)
            {
              if(mpa_currentHandler == nullptr)
                {
                  mpa_currentHandler =
                    new MsIdentificationTableMsRunStatisticsHandler;
                  identificationDataSource->getMsRunSp()->checkMsRunStatistics(
                    mpa_currentHandler);
                  if(!mpa_currentHandler->shouldStop())
                    {
                      // if statistics computing is interrupted : don't take
                      // into account results because it is partial
                      m_identificationReady.push_back(
                        identificationDataSource.get());
                    }

                  delete mpa_currentHandler;
                  mpa_currentHandler = nullptr;
                }
            }
        }
      catch(pappso::PappsoException &error)
        {
          // error while computing
          qDebug() << error.qwhat();
          m_identificationError.push_back(identificationDataSource.get());
        }
    }
  else
    {
      // file not found
      qDebug();
      m_identificationFileNotFound.push_back(identificationDataSource.get());
    }
}

void
MsIdListWorkerStatus::changeWaitingQueue(int row [[maybe_unused]])
{
  m_waitingComputing.clear();
  qDebug() << m_waitingComputing.size();
}
