/***************************************************************************
 *   copyright       : (C) 2009-2022 by Pascal Brachet                     *
 *   https://www.xm1math.net/algobox/                                      *
 *                                                                         *
 *   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; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   @license GPL-2.0+ <https://spdx.org/licenses/GPL-2.0+.html>           *
 ***************************************************************************/

#include "browserdialog.h"
#include <QUrl>
#include <QTextCursor>
#include <QTimer>
#include <QDebug>
#include <QApplication>
#include <QTextCharFormat>
#include <QFontDatabase>
#include <QMouseEvent>
#include <QTextStream>
#include <QWebChannel>
#include <QSplashScreen>
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    #include <QtCore/QTextCodec>
#else
    #include <QtCore5Compat/QTextCodec>
#endif



BrowserDialog::BrowserDialog(QWidget *parent,QString fichier,bool blackconsole)
    :QDialog( parent)
{
hide();
QPixmap pixmap(400,163);
if (qApp->devicePixelRatio()>=2)
{
pixmap.load(":/images/splash@2x.png");
pixmap.setDevicePixelRatio(qApp->devicePixelRatio());
}
else pixmap.load(":/images/splash.png");

QSplashScreen *splash = new QSplashScreen(pixmap);
splash->resize(400,163);
splash->show();

ui.setupUi(this);
splash->finish(this);

connect(ui.webView, SIGNAL(loadFinished(bool)), SLOT(finishLoading(bool)));
ui.testerButton->setEnabled(false);
ui.suivantButton->setEnabled(false);
ui.stopButton->setEnabled(false);
ui.textEditPas->hide();
ui.labelProcess->hide();
setModal(true);
QFontDatabase fdb;
QStringList xf = fdb.families();
QString deft;
QTextCharFormat output_format;
if (xf.contains("Liberation Mono",Qt::CaseInsensitive)) deft="Liberation Mono";
else if (xf.contains("DejaVu Sans Mono",Qt::CaseInsensitive)) deft="DejaVu Sans Mono";
#if defined(Q_OS_WIN32)
else if (xf.contains("Courier New",Qt::CaseInsensitive)) deft="Courier New";
#endif
else deft=qApp->font().family();

#if defined(Q_OS_MAC)
if (xf.contains("Monaco",Qt::CaseInsensitive)) deft="Monaco";
else if (xf.contains("Courier New",Qt::CaseInsensitive)) deft="Courier New";
else if (xf.contains("PT Mono",Qt::CaseInsensitive)) deft="PT Mono";
else if (xf.contains("Andale Mono",Qt::CaseInsensitive)) deft="Andale Mono";
else deft=qApp->font().family();
#endif

output_format.setFont(QFont(deft,qApp->font().pointSize()));
// output_format.setFontFamily(deft);
// output_format.setFontFixedPitch(true);
// output_format.setFontItalic(false);
//output_format.setFontPointSize(qApp->font().pointSize()-1);
ui.textEdit->setCurrentCharFormat(output_format);
ui.textEditPas->setCurrentCharFormat(output_format);

QPalette palette=ui.textEdit->palette();
if (blackconsole)
{
palette.setColor(QPalette::Active, QPalette::Base, QColor(52,49,49));
palette.setColor(QPalette::Active, QPalette::Text, QColor(255,255,255));
palette.setColor(QPalette::Inactive, QPalette::Base, QColor(52,49,49));
palette.setColor(QPalette::Inactive, QPalette::Text, QColor(255,255,255));
}
else
{
palette.setColor(QPalette::Active, QPalette::Base, QColor(255,255,255));
palette.setColor(QPalette::Active, QPalette::Text, QColor(0,0,0));
palette.setColor(QPalette::Inactive, QPalette::Base, QColor(255,255,255));
palette.setColor(QPalette::Inactive, QPalette::Text, QColor(0,0,0));
} 

ui.textEdit->setPalette(palette);
ui.textEditPas->setPalette(palette);

highlighter = new ConsoleHighlighter(ui.textEdit->document(),blackconsole);
highlighterPas = new LogHighlighter(ui.textEditPas->document(),blackconsole);

ui.pdfButton->setEnabled(false);
ui.checkBoxPasAPas->setEnabled(false);
ui.suivantButton->setEnabled(false);
ui.stopButton->setEnabled(false);
ui.testerButton->setEnabled(false);

page=new AlgoWebPage(ui.webView,ui.textEdit);
ui.webView->setPage(page);

QWebChannel *channel = new QWebChannel();
page->setWebChannel(channel);
channel->registerObject(QString("BrowserDialog"), this);
page->load(QUrl::fromLocalFile(fichier));
ui.textEdit->clear();
ui.textEditPas->clear();
//ui.testerButton->setEnabled(true);
connect(ui.testerButton, SIGNAL(clicked()),this, SLOT(LancerAlgo()));
connect(ui.suivantButton, SIGNAL(clicked()),this, SLOT(ContinuerPasAPas()));
connect(ui.stopButton, SIGNAL(clicked()),this, SLOT(StopperPasAPas()));
connect(ui.pdfButton, SIGNAL(clicked()),ui.webView, SLOT(exporterPdf()));
connect(ui.textEdit, SIGNAL(done()),this, SLOT(setFocus()));

}

BrowserDialog::~BrowserDialog(){
page->arreter();
page->stopaffichage();
}

void BrowserDialog::accept()
{
page->arreter();
page->stopaffichage();
QDialog::accept();
}

void BrowserDialog::closeEvent(QCloseEvent *e)
{
page->arreter();
page->stopaffichage();
e->accept();
}


void BrowserDialog::scriptAfficher(QString msg,bool newline)
{
if (!msg.isEmpty())
  {
  QTextCursor cur=ui.textEdit->textCursor();
  if (newline) 
    {
    ui.textEdit->insertPlainText(msg+"\n");
    }
  else 
    {
    ui.textEdit->insertPlainText(msg);
    }
  cur.movePosition(QTextCursor::End,QTextCursor::MoveAnchor);
  ui.textEdit->setTextCursor(cur);
  ui.textEdit->scrollDown();
  }
page->minipause();
}

void BrowserDialog::scriptAfficherVariables(QString msg,bool newline)
{
if (msg.isEmpty()) return;
QTextCursor cur=ui.textEditPas->textCursor();
if (newline) 
  {
  ui.textEditPas->insertPlainText(msg+"\n");
  }
else 
  {
  ui.textEditPas->insertPlainText(msg);
  }
cur.movePosition(QTextCursor::End,QTextCursor::MoveAnchor);
ui.textEditPas->setTextCursor(cur);
}

void BrowserDialog::scriptLaunched()
{
// if (ui.checkBoxPasAPas->isChecked())
//   {
//   ui.suivantButton->setEnabled(true);
//   ui.stopButton->setEnabled(true);
//   }
ui.checkBoxPasAPas->setEnabled(false);
//ui.testerButton->setText(QString::fromUtf8("Exécution en cours"));
ui.testerButton->setEnabled(false);
ui.pdfButton->setEnabled(false);
ui.labelProcess->show();
}

void BrowserDialog::scriptFinished()
{
QString output=ui.textEdit->toPlainText();
QString ligne;
QVariant data;
QTextCodec *codec = QTextCodec::codecForName("UTF-8");
QTextStream l(&output,QIODevice::ReadOnly);
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
l.setCodec(codec);
#else
l.setEncoding(QStringConverter::Encoding::Utf8);
#endif
while (!l.atEnd()) 
	{
	ligne=l.readLine();
	page->runJavaScript("ALGOBOX_AJOUTE_RESULTAT(\""+ligne.trimmed()+"\");");
	}
ui.labelProcess->hide();
ui.testerButton->setText(QString::fromUtf8("Lancer Algorithme"));
ui.testerButton->setEnabled(true);
ui.checkBoxPasAPas->setEnabled(true);
ui.suivantButton->setEnabled(false);
ui.stopButton->setEnabled(false);
ui.webView->setFocus();
QPoint pos(0,0);
QMouseEvent event(QEvent::MouseButtonPress,pos,Qt::LeftButton, Qt::LeftButton,Qt::NoModifier);
QApplication::sendEvent(ui.webView, &event);
ui.pdfButton->setEnabled(true);
}

void BrowserDialog::scriptEffacer()
{
ui.textEdit->clear();
ui.textEditPas->clear();
}

void BrowserDialog::LancerAlgo()
{
ui.textEdit->clear();
ui.textEditPas->clear();
if (ui.checkBoxPasAPas->isChecked()) ui.textEditPas->show();
else ui.textEditPas->hide();
ui.stopButton->setEnabled(true);
QTimer::singleShot(100, this, SLOT(ExecuterAlgo()));
}

void BrowserDialog::ExecuterAlgo()
{
ui.textEdit->insertPlainText(QString::fromUtf8("***Lancement de l'algorithme***"));
//ui.textEdit->insertPlainText(QString::fromUtf8("***L'algorithme contient une erreur : impossible de le lancer***\n***Vérifiez la syntaxe des affectations et des conditions***\n"));  
if (ui.checkBoxPasAPas->isChecked()) page->runJavaScript("ALGOBOX_ALGO(true);");
else page->runJavaScript("ALGOBOX_ALGO(false);");
}

void BrowserDialog::ContinuerPasAPas()
{
ui.labelProcess->show();
page->continuer();
}

void BrowserDialog::StopperPasAPas()
{
ui.labelProcess->hide();
if (ui.suivantButton->isEnabled()) page->arreter();
else page->runJavaScript("ALGOBOX_EMERGENCY_STOP=true;");
}

void BrowserDialog::scriptDebutPause()
{
ui.suivantButton->setEnabled(true);
ui.labelProcess->hide();
//ui.stopButton->setEnabled(true);
}

void BrowserDialog::scriptFinPause()
{
ui.suivantButton->setEnabled(false);
ui.labelProcess->show();
//ui.stopButton->setEnabled(false);
}

void BrowserDialog::finishLoading(bool)
{
ui.testerButton->setEnabled(true);
ui.checkBoxPasAPas->setEnabled(true);
ui.suivantButton->setEnabled(false);
ui.stopButton->setEnabled(false);
ui.pdfButton->setEnabled(true);
raise();
show();
}
