/***************************************************************************
**
**  This file is part of QGpCoreTools.
**
**  This library is free software; you can redistribute it and/or
**  modify it under the terms of the GNU Lesser General Public
**  License as published by the Free Software Foundation; either
**  version 2.1 of the License, or (at your option) any later version.
**
**  This file 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 Lesser General Public
**  License for more details.
**
**  You should have received a copy of the GNU Lesser General Public
**  License along with this library; if not, write to the Free Software
**  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
**
**  See http://www.geopsy.org for more information.
**
**  Created: 2010-09-07
**  Copyright: 2010-2019
**    Marc Wathelet (LGIT, Grenoble, France)
**
***************************************************************************/

#include "Global.h"
#include "CacheProcess.h"

namespace QGpCoreTools {

  /*!
    \class CacheProcess CacheProcess.h
    \brief A list of CacheItem to be processed

    This list is used to predict the usage of the CacheItem. Each process that uses CacheItem in a known sequence
    should create such an object and add items in order of their expected usage. Items without CacheProcess
    are considered in a classical way with their last access time. One CacheItem can have several CacheProcess
    attached to it. The next predicted time of usage is the minimum returned by all these processes. Inside the
    list of allocated items the one with the maximum predicted time of usage is selected for deallocation. Items
    without CacheProcess attached have predicted time of usage set to infinite (maximum integer value).
  */

  /*!
    Removes all links to this process
  */
  CacheProcess::~CacheProcess()
  {
    for(QHash<const CacheItem *, int>::iterator it=_items.begin(); it!=_items.end(); it++) {
      it.key()->removeProcess(this);
    }
  }

  /*!
    \fn void CacheProcess::add(CacheItem * item);

    Add \a item. The order must must be the same as the real processing.

    \sa next()
  */

  /*!
    \fn void remove(const CacheItem * item)
    Called mainly by CacheItem destructor
  */

  /*!
    \fn void CacheProcess::begin()

    Call it right begin using the first item
  */

  /*!
    \fn void CacheProcess::next()

    Call it after using each item added by add()
  */

  /*!
    Calculated predicted time of usage for \a item based on past time spent.
    If no statistics are available, current time is returned.
  */
  quint64 CacheProcess::predictedTime(const CacheItem * item) const
  {
    int index=_items[item];
    if(index>_current) { // Signal must be still processed
      quint64 now=ApplicationClock::elapsed();
      double rate=now-_start;
      if(rate<1.0) {
        rate=1.0;
      }
      if(_current>1) { // Else, elapsed time is considered as the time of one step
        rate/=(double)_current;
      }
      return now+(quint64)round(rate*(index-_current));
    } else if(index==_current) {
      return ApplicationClock::elapsed();
    } else {
      return MAXIMUM_APPLICATION_LIFETIME;
    }
  }

} // namespace QGpCoreTools
