/****************************************************************************
** Dooble - The Secure Internet Web Browser
**
** Copyright (c) 2012 Alexis Megas,
** Gunther van Dooble, and the Dooble Team.
** All rights reserved.
**
** License: GPL2 only:
** This program 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; version 2 of the License only.
**
** This program 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 this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
** or see here: http://www.gnu.org/licenses/gpl.html
**
** For the WebKit library, please see: http://webkit.org.
**
** THE CODE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY
** EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
** ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
** GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
** IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
** ARISING IN ANY WAY OUT OF THE USE OF THIS APPLICATION, EVEN IF ADVISED
** OF THE POSSIBILITY OF SUCH DAMAGE.
**
** Please report all praise, requests, bugs, and problems to the project
** team and administrators: http://sf.net/projects/dooble.
**
** You can find us listed at our project page. New team members are welcome.
** The name of the authors should not be used to endorse or promote products
** derived from Dooble without specific prior written permission.
** If you use this code for other projects, please let us know.
**
** Web sites:
**   http://sf.net/projects/dooble
**   http://dooble.sf.net
****************************************************************************/

#include <QKeyEvent>
#include <QSettings>
#include <QScrollBar>

#include "dmisc.h"
#include "dooble.h"
#include "derrorlog.h"

derrorlog::derrorlog(void):QMainWindow()
{
  ui.setupUi(this);
#ifdef Q_WS_MAC
  setAttribute(Qt::WA_MacMetalStyle, false);
  statusBar()->setSizeGripEnabled(false);
#endif
  connect(ui.action_Close,
	  SIGNAL(triggered(void)),
	  this,
	  SLOT(slotClose(void)));
  connect(ui.actionClear_Log,
	  SIGNAL(triggered(void)),
	  this,
	  SLOT(slotClear(void)));
  connect(ui.action_Find, SIGNAL(triggered(void)), this,
	  SLOT(slotShowFind(void)));
  connect(ui.hideFindToolButton, SIGNAL(clicked(void)), this,
	  SLOT(slotHideFind(void)));
  connect(ui.findLineEdit, SIGNAL(returnPressed(void)), this,
	  SLOT(slotNextFind(void)));
  connect(ui.findLineEdit, SIGNAL(textEdited(const QString &)), this,
	  SLOT(slotNextFind(const QString &)));
  connect(ui.nextToolButton, SIGNAL(clicked(void)),
	  this, SLOT(slotNextFind(void)));
  connect(ui.previousToolButton, SIGNAL(clicked(void)),
	  this, SLOT(slotPreviousFind(void)));

  /*
  ** The logError() method may be called from multiple threads.
  */

  connect(this,
	  SIGNAL(appendToLog(const QString &)),
	  this,
	  SLOT(slotAppendToLog(const QString &)),
	  Qt::QueuedConnection);

  /*
  ** We can't call slotSetIcons() here because we may not be in the
  ** proper state.
  */

  slotHideFind();
}

void derrorlog::saveState(void)
{
  /*
  ** geometry() may return (0, 0) coordinates if the window is
  ** not visible.
  */

  if(!isVisible())
    return;

  if(dmisc::isGnome())
    dooble::s_settings["errorLog/geometry"] = geometry();
  else
    dooble::s_settings["errorLog/geometry"] = saveGeometry();

  QSettings settings;

  if(dmisc::isGnome())
    settings.setValue("errorLog/geometry", geometry());
  else
    settings.setValue("errorLog/geometry", saveGeometry());
}

void derrorlog::slotClose(void)
{
  close();
}

void derrorlog::closeEvent(QCloseEvent *event)
{
  saveState();
  QMainWindow::closeEvent(event);
}

void derrorlog::keyPressEvent(QKeyEvent *event)
{
  if(event)
    {
      if(event->key() == Qt::Key_Escape &&
	 ui.findFrame->isVisible())
	ui.findFrame->setVisible(false);
      else if(event->key() == Qt::Key_Escape)
	close();
    }

  QMainWindow::keyPressEvent(event);
}

void derrorlog::slotShow(void)
{
  if(!isVisible())
   {
     /*
     ** Don't annoy the user.
     */

     if(dooble::s_settings.contains("errorLog/geometry"))
       {
	 if(dmisc::isGnome())
	   setGeometry(dooble::s_settings.value("errorLog/geometry",
						QRect(100, 100, 800, 600)).
		       toRect());
	 else
	   {
	     QByteArray g(dooble::s_settings.value("errorLog/geometry").
			  toByteArray());

	     if(!restoreGeometry(g))
	       setGeometry(100, 100, 800, 600);
	   }
       }
     else
       setGeometry(100, 100, 800, 600);
   }

  showNormal();
  raise();
}

void derrorlog::slotSetIcons(void)
{
  QSettings settings
    (dooble::s_settings.value("iconSet").toString(), QSettings::IniFormat);

  settings.beginGroup("errorLog");
  ui.actionClear_Log->setIcon
    (QIcon(settings.value("actionClearLog").toString()));
  ui.action_Close->setIcon(QIcon(settings.value("actionClose").toString()));
  ui.action_Find->setIcon(QIcon(settings.value("actionFind").toString()));
  ui.hideFindToolButton->setIcon
    (QIcon(settings.value("hideFindToolButton").toString()));
  ui.nextToolButton->setIcon
    (QIcon(settings.value("nextToolButton").toString()));
  ui.previousToolButton->setIcon
    (QIcon(settings.value("previousToolButton").toString()));
  setWindowIcon(QIcon(settings.value("windowIcon").toString()));
}

void derrorlog::logError(const QString &error)
{
  emit appendToLog(error);
}

bool derrorlog::hasErrors(void) const
{
  return !ui.textBrowser->document()->isEmpty();
}

void derrorlog::slotAppendToLog(const QString &error)
{
  /*
  ** Ignore duplicate errors.
  */

  if(error == m_lastError)
    return;

  m_lastError = error;

  QString text("");
  QDateTime now(QDateTime::currentDateTime());

  text.append(now.toString(Qt::ISODate));
  text.append("\r");
  text.append(error);
  text.append("\r");
  ui.textBrowser->append(text);
  emit errorLogged();
}

void derrorlog::slotClear(void)
{
  m_lastError.clear();
  ui.textBrowser->clear();
}

void derrorlog::slotNextFind(void)
{
  slotNextFind(ui.findLineEdit->text());
}

void derrorlog::slotNextFind(const QString &text)
{
  static QPalette lineEditPalette(ui.findLineEdit->palette());
  QTextDocument::FindFlags findFlags = 0;

  if(ui.matchCaseCheckBox->isChecked())
    findFlags |= QTextDocument::FindCaseSensitively;

  if(ui.textBrowser->find(text, findFlags) || text.isEmpty())
    {
      ui.findLineEdit->setPalette(lineEditPalette);

      if(text.isEmpty())
        ui.textBrowser->moveCursor(QTextCursor::PreviousCharacter);
    }
  else
    {
      if(ui.textBrowser->textCursor().anchor() ==
	 ui.textBrowser->textCursor().position())
	{
	  if(!ui.textBrowser->textCursor().atEnd())
	    {
	      QColor color(240, 128, 128); // Light Coral
	      QPalette palette(ui.findLineEdit->palette());

	      palette.setColor(ui.findLineEdit->backgroundRole(), color);
	      ui.findLineEdit->setPalette(palette);
	    }
	  else
	    ui.textBrowser->moveCursor(QTextCursor::Start);
	}
      else
	{
	  ui.textBrowser->moveCursor(QTextCursor::Start);
	  slotNextFind(text);
	}
    }
}

void derrorlog::slotPreviousFind(void)
{
  slotPreviousFind(ui.findLineEdit->text());
}

void derrorlog::slotPreviousFind(const QString &text)
{
  static QPalette lineEditPalette(ui.findLineEdit->palette());
  QTextDocument::FindFlags findFlags = QTextDocument::FindBackward;

  if(ui.matchCaseCheckBox->isChecked())
    findFlags |= QTextDocument::FindCaseSensitively;

  if(ui.textBrowser->find(text, findFlags) || text.isEmpty())
    ui.findLineEdit->setPalette(lineEditPalette);
  else
    {
      if(ui.textBrowser->textCursor().anchor() ==
	 ui.textBrowser->textCursor().position())
	{
	  if(!ui.textBrowser->textCursor().atEnd())
	    {
	      QColor color(240, 128, 128); // Light Coral
	      QPalette palette(ui.findLineEdit->palette());

	      palette.setColor(ui.findLineEdit->backgroundRole(), color);
	      ui.findLineEdit->setPalette(palette);
	    }
	  else
	    ui.textBrowser->moveCursor(QTextCursor::End);
	}
      else
	{
	  ui.textBrowser->moveCursor(QTextCursor::End);
	  slotPreviousFind(text);
	}
    }
}

void derrorlog::slotHideFind(void)
{
  ui.findFrame->setVisible(false);
}

void derrorlog::slotShowFind(void)
{
  ui.findFrame->setVisible(true);
  ui.findLineEdit->setFocus();
  ui.findLineEdit->selectAll();

#ifdef Q_WS_MAC
  static int fixed = 0;

  if(!fixed)
    {
      QColor color(255, 255, 255);
      QPalette palette(ui.findLineEdit->palette());

      palette.setColor(ui.findLineEdit->backgroundRole(), color);
      ui.findLineEdit->setPalette(palette);
      fixed = 1;
    }
#endif
}

void derrorlog::clear(void)
{
  slotClear();
}
