/***************************************************************************
**
**  This file is part of QGpGuiTools.
**
**  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: 2005-07-01
**  Copyright: 2005-2019
**    Marc Wathelet
**    Marc Wathelet (LGIT, Grenoble, France)
**
***************************************************************************/

#include "LogView.h"

namespace QGpGuiTools {

  /*!
    A LogView is a QWidget but also an AbstractStream that can be automatically
    deleted by the log manager at application level. To prevent abusive deletion
    while still linked to its QWidget parent, an auto-reference is added in this
    constructor. As a matter of consequence, you cannot delete this object (or let
    its parent destroying it) directly with delete. Instead, call remove().
  */
  LogView::LogView(QWidget * parent)
      : QTextBrowser(parent), AbstractStream()
  {
    TRACE;
    setAcceptRichText (false);
#ifdef Q_OS_MAC
    setFontFamily("Courier");
#else
    setFontFamily("Monospace");
#endif
    setLineWrapMode(QTextEdit::NoWrap);
    // Avoid more than 2 refresh of the widget per second
    _clock.setInterval(500);
    connect(&_clock, SIGNAL(timeout()), this, SLOT(flushBuffer()) );
    connect(this, SIGNAL(bufferReady()), this, SLOT(wakeUp()), Qt::QueuedConnection);

    _minimumLineCount=2;

    addReference(); // Avoid deletion by stream management
  }

  QSize LogView::sizeHint() const
  {
    QSize s=QTextBrowser::sizeHint();
    QFontMetrics f(font());
    s.setHeight(f.height()*(_minimumLineCount+1));
    return s;
  }

  /*!
    Detach from its QWidget parent, if any and delete this oblect
  */
  void LogView::remove()
  {
    TRACE;
    hide();
    setParent(0);
    removeReference(this);
  }

  void LogView::operator=(LogView& o)
  {
    TRACE;
    lock ();
    o.lock ();
    _buffer=o._buffer;
    setText(o.toPlainText());
    o.unlock();
    unlock();
    flushBuffer();
  }

  void LogView::clear()
  {
    TRACE;
    lock ();
    _buffer.clear();
    QTextBrowser::clear();
    unlock();
  }

  void LogView::flushBuffer()
  {
    TRACE;
    lock ();
    if(_buffer.isEmpty()) {
      TRACE_BUG;
      _clock.stop();
    } else if(_buffer.length()>1000000) {
      TRACE_BUG;
      _buffer+= "\n\n Buffer overflow!\nFreezing stream...";
      QTextBrowser::append( "\n\n [...] \n\n" );
      _buffer=_buffer.right(500000);
    } else {
      if(_buffer.endsWith("\n")) {
        TRACE_BUG;
        _buffer.chop(1);
        QTextBrowser::append(_buffer);
        _buffer.clear();
      } else {
        TRACE_BUG;
        int lastLF=_buffer.lastIndexOf("\n");
        if(lastLF > -1) {
          QTextBrowser::append(_buffer.left(lastLF) );
          _buffer=_buffer.right(_buffer.length() - lastLF - 1);
        }
      }
    }
    unlock();
  }

  void LogView::wakeUp()
  {
    TRACE;
    lock();
    if( !_clock.isActive()) _clock.start();
    unlock();
  }

  void LogView::sendToStream(const QString& val)
  {
    _buffer+=val;
    if(!_clock.isActive()) emit bufferReady();
  }

  void LogView::flushStream()
  {
    if(!_clock.isActive()) emit bufferReady();
  }

  void LogView::contextMenuEvent(QContextMenuEvent * e)
  {
    TRACE;
    QMenu * m=createStandardContextMenu(e->pos());
    m->addAction(tr("Clear all"), this, SLOT(clear()));
    m->popup(mapToGlobal(e->pos()));
    //delete m;
  }

} // namespace QGpGuiTools
