/***************************************************************************
**
**  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-11
**  Copyright: 2010-2019
**    Marc Wathelet (LGIT, Grenoble, France)
**
***************************************************************************/

#include "AbstractStream.h"
#include "CoreApplication.h"
#include "Trace.h"

namespace QGpCoreTools {

  int AbstractStream::_applicationVerbosity=0;

  /*!
    \class AbstractStream AbstractStream.h
    \brief Brief description of class still missing

    Full description of class still missing
  */

  /*!
    Description of constructor still missing
  */
  AbstractStream::AbstractStream()
  {
    TRACE;
    _active=true;
    _lineOpen=false;
    _prefixType=NoPrefix;
    _next=nullptr;
    _previous=nullptr;
  }

  AbstractStream::~AbstractStream()
  {
    TRACE;
    if(_previous) {
      removeReference(_previous);
    }
  }

  void AbstractStream::setApplicationVerbosity(int verbosity)
  {
    _applicationVerbosity=verbosity;
    QTextStream sOut(stderr);
    if(_applicationVerbosity<0) {
      sOut << "Negative verbosity not allowed (option -verbosity)" << Qt::endl;
      ::exit(2);
    }
  }

  void AbstractStream::setPrevious(AbstractStream * s)
  {
    if(_previous) {
      AbstractStream::removeReference(_previous);
    }
    _previous=s;
    if(_previous) {
      _previous->addReference();
    }
  }

  /*!
    If \a prefix contains "%t", it is replaced by current time
  */
  void AbstractStream::setPrefix(const QString & prefix)
  {
    if(prefix.isEmpty()) {
      _prefixType=NoPrefix;
    } else {
      int i=prefix.indexOf("%t");
      if(i==-1) {
        _prefixType=String;
        _prefix1=prefix;
      } else {
        _prefixType=TimeStamp;
        _prefix1=prefix.left(i);
        _prefix2=prefix.mid(i+2);
      }
      _lineOpen=false; // Disregarded when in NoPrefix mode
    }
  }

  QString AbstractStream::prefix() const
  {
    switch(_prefixType) {
    case NoPrefix:
      break;
    case String:
      return _prefix1;
    case TimeStamp:
      return _prefix1+"%t"+_prefix2;
    }
    return QString();
  }

  inline QString AbstractStream::timeStampedPrefix()
  {
    QString prefix=_prefix1;
    prefix+=QDateTime::currentDateTime().toString("ddd MMM dd hh:mm:ss yyyy");
    prefix+=_prefix2;
    return prefix;
  }

  /*!
    Return previous active status
  */
  bool AbstractStream::setActive(bool a)
  {
    bool prev;
    _mutex.lock();
    prev=_active;
    _active=a;
    _mutex.unlock();
    return prev;
  }

  bool AbstractStream::isActive() const
  {
    _mutex.lock();
    bool a=_active;
    _mutex.unlock();
    return a;
  }

  void AbstractStream::send(int verbosity, const QString& val)
  {
    _mutex.lock();
    if(_active && verbosity<=_applicationVerbosity) {
      bool lineEnd=val.endsWith("\n");
      switch(_prefixType) {
      case NoPrefix:
        sendToStream(val);
        break;
      case String:
        if(!_lineOpen) {
          sendToStream(_prefix1);
          _lineOpen=true;
        }
        if(val.lastIndexOf("\n", -2)>-1) {
          QString s=val;
          s.replace("\n", "\n"+_prefix1);
          if(lineEnd) {
            s.chop(_prefix1.count());
          }
          sendToStream(s);
        } else {
          sendToStream(val);
        }
        break;
      case TimeStamp: {
          QString prefix=timeStampedPrefix();
          if(!_lineOpen) {
            sendToStream(prefix);
            _lineOpen=true;
          }
          if(val.contains("\n")) {
            QString s=val;
            s.replace("\n", "\n"+prefix);
            sendToStream(s);
          } else {
            sendToStream(val);
          }
        }
        break;
      }
      if(lineEnd) {
        flushStream();
      }
      _lineOpen=!lineEnd;
    }
    _mutex.unlock();
  }

} // namespace QGpCoreTools
