/***************************** LICENSE START ***********************************

 Copyright 2012 ECMWF and INPE. This software is distributed under the terms
 of the Apache License version 2.0. In applying this license, ECMWF does not
 waive the privileges and immunities granted to it by virtue of its status as
 an Intergovernmental Organization or submit itself to any jurisdiction.

 ***************************** LICENSE END *************************************/

#include "MvQHelpBrowser.h"
#include "MvQWebViewSearchLine.h"
#include "MvQSearchLinePanel.h"

#include <QAction>
#include <QApplication>
#include <QCloseEvent>
#include <QDebug>
#include <QDesktopServices>
#include <QDialogButtonBox>
#include <QFileInfo>
#include <QHBoxLayout>
#include <QHelpContentWidget>
#include <QHelpEngine>
#include <QHelpIndexWidget>
#include <QLabel>
#include <QLineEdit>
#include <QList>
#include <QNetworkAccessManager>
#include <QPushButton>
#include <QSettings>
#include <QSplitter>
#include <QString>
#include <QTabWidget>
#include <QTextBrowser>
#include <QUrl>
#include <QVariant>
#include <QVBoxLayout>
#include <QWebView>
#include <QWebPage>

#include "MvQMethods.h"
#include "MvQTheme.h"

MvQHelpBrowser::MvQHelpBrowser(QWidget* parent) :
    MvQMainWindow(parent)
{
    // setAttribute(Qt::WA_DeleteOnClose);

    setWindowTitle("Metview - Help");

    // Initial size
    setInitialSize(1100, 800);

    //--------------------------------------
    // Set the help engine
    //--------------------------------------

    // QFileInfo fileInfo("/tmp/dummy-user/metview_qt_documentation/metview_confluence/metview_collection.qhc");
    const QString share_dir = QString(getenv("METVIEW_DIR_SHARE"));
    QFileInfo fileInfo(share_dir + QString("/etc/metview_collection.qhc"));
    QHelpEngine* engine_ = new QHelpEngine(fileInfo.absoluteFilePath(), this);
    engine_->setupData();

    //--------------------------------------
    // Main Layout - splitter
    //--------------------------------------

    QWidget* w = new QWidget(this);
    QVBoxLayout* mainLayout = new QVBoxLayout(w);
    mainLayout->setSpacing(0);
    mainLayout->setContentsMargins(1, 1, 1, 1);

    setCentralWidget(w);

    // Splitter
    splitter_ = new QSplitter(this);
    mainLayout->addWidget(splitter_);

    //--------------------------------------
    // Left - tab Content
    //--------------------------------------


    QTabWidget* tab = new QTabWidget(this);
    splitter_->addWidget(tab);

    tab->addTab(engine_->contentWidget(), tr("Content"));

    //--------------------------------------
    // Left - tab Index
    //--------------------------------------

    lookFor_label_ = new QLabel(tr("Look for:"), this);
    lookFor_edit_ = new QLineEdit(this);
    lookFor_label_->setBuddy(lookFor_edit_);
    connect(lookFor_edit_, SIGNAL(textChanged(const QString&)), engine_->indexWidget(), SLOT(filterIndices(const QString&)));

    QWidget* itab_w = new QWidget(this);
    QVBoxLayout* ilayout = new QVBoxLayout(itab_w);
    ilayout->addWidget(lookFor_label_);
    ilayout->addWidget(lookFor_edit_);
    ilayout->addWidget(engine_->indexWidget());

    tab->addTab(itab_w, tr("Index"));

    //--------------------------------------
    // Right - content view widget
    //--------------------------------------

    // set web view text encoding
    webView_ = new QWebView(this);
    webView_->settings()->setDefaultTextEncoding("utf-8");

    // set the documentation css style
    // QUrl myCssFileURL= QUrl("file:///tmp/dummy-user/metview_qt_documentation/metview_confluence/METV/styles/site.css");

    // ini juanjo 03.09.2013
    // QUrl myCssFileURL= QUrl(QString("file://")+share_dir+QString("/etc/help.css"));
    // webView_->settings()->setUserStyleSheetUrl(myCssFileURL);
    // end juanjo 03.09.2013


    // use a request manager able to handle "qthelp" requests
    QNetworkAccessManager* current_manager = webView_->page()->networkAccessManager();
    MvHelpNetworkAccessManager* newManager = new MvHelpNetworkAccessManager(engine_, current_manager, this);
    webView_->page()->setNetworkAccessManager(newManager);
    webView_->page()->setForwardUnsupportedContent(false);

    QWebPage* page_ = webView_->page();
    page_->setLinkDelegationPolicy(QWebPage::DelegateExternalLinks);

    connect(engine_->contentWidget(), SIGNAL(linkActivated(const QUrl&)), this, SLOT(setWebSource(const QUrl&)));
    connect(engine_->indexWidget(), SIGNAL(linkActivated(const QUrl&, const QString&)), this, SLOT(setWebSource(const QUrl&)));
    connect(webView_, SIGNAL(linkClicked(const QUrl&)), this, SLOT(setWebSource(const QUrl&)));

    //--------------------------------------
    // Right - content view layout
    //--------------------------------------

    QWidget* rw = new QWidget(this);
    QVBoxLayout* rLayout = new QVBoxLayout(rw);
    rLayout->setSpacing(0);
    rLayout->addWidget(webView_);
    rLayout->setStretchFactor(webView_, 1);

    //--------------------------
    // Right - Find widget
    //--------------------------

    search_ = new MvQWebViewSearchLine(webView_, tr("&Find:"));
    searchPanel_ = new MvQSearchLinePanel();
    searchPanel_->addSearchLine(search_, webView_);
    searchPanel_->setHidden(true);
    rLayout->addWidget(searchPanel_);
    splitter_->addWidget(rw);

    //--------------------------------------
    // Setup actions for toolbars and menus
    //--------------------------------------

    setupNavigateActions();
    setupHelpActions();
    setupSearchActions();

    setupMenus(menuItems_);

    //-------------------------
    // Settings
    //-------------------------

    readSettings();

    //-------------------------
    // Load documentation home page
    //-------------------------

    docHome();
}

MvQHelpBrowser::~MvQHelpBrowser()
{
    writeSettings();
}

void MvQHelpBrowser::closeEvent(QCloseEvent* event)
{
    // emit aboutToClose(this);
    close();
    event->accept();
}

void MvQHelpBrowser::setupSearchActions()
{
    // Find
    QAction* actionFind_ = MvQMainWindow::createAction(MvQMainWindow::FindAction, this);
    connect(actionFind_, SIGNAL(triggered(bool)), searchPanel_, SLOT(setHidden(bool)));

    // Find Next
    QAction* actionFindNext_ = MvQMainWindow::createAction(MvQMainWindow::FindNextAction, this);
    connect(actionFindNext_, SIGNAL(triggered(bool)), searchPanel_, SLOT(slotFindNext(bool)));

    // Find Previous
    QAction* actionFindPrev_ = MvQMainWindow::createAction(MvQMainWindow::FindPreviousAction, this);
    connect(actionFindPrev_, SIGNAL(triggered(bool)), searchPanel_, SLOT(slotFindPrev(bool)));

    MvQMainWindow::MenuType menuType = MvQMainWindow::EditMenu;

    menuItems_[menuType].push_back(new MvQMenuItem(actionFind_, MvQMenuItem::MenuTarget));
    menuItems_[menuType].push_back(new MvQMenuItem(actionFindNext_, MvQMenuItem::MenuTarget));
    menuItems_[menuType].push_back(new MvQMenuItem(actionFindPrev_, MvQMenuItem::MenuTarget));
}

void MvQHelpBrowser::setupNavigateActions()
{
    // Back
    actionBack_ = new QAction(this);
    actionBack_->setIcon(QApplication::style()->standardIcon(QStyle::SP_ArrowLeft));
    actionBack_->setToolTip(tr("Back"));
    actionBack_->setText(tr("Back"));
    actionBack_->setShortcut(tr("Alt+Left"));

    connect(actionBack_, SIGNAL(triggered()), webView_, SLOT(back()));

    // Forward
    actionForward_ = new QAction(this);
    actionForward_->setIcon(QApplication::style()->standardIcon(QStyle::SP_ArrowRight));
    actionForward_->setToolTip(tr("Forward"));
    actionForward_->setText(tr("Forward"));
    actionForward_->setShortcut(tr("Alt+Right"));

    connect(actionForward_, SIGNAL(triggered()), webView_, SLOT(forward()));

    // Home
    actionHome_ = new QAction(this);
    actionHome_->setIcon(QPixmap(QString::fromUtf8(":/desktop/home.svg")));
    actionHome_->setToolTip(tr("Metview Documentation home"));
    actionHome_->setText(tr("Mv Doc home"));
    actionHome_->setIconText(tr("home"));
    actionHome_->setShortcut(tr("Alt+Home"));

    connect(actionHome_, SIGNAL(triggered()), this, SLOT(docHome()));

    QAction* sep = new QAction(this);
    sep->setSeparator(true);

    MvQMainWindow::MenuType menuType = MvQMainWindow::NavigateMenu;

    menuItems_[menuType].push_back(new MvQMenuItem(actionBack_));
    menuItems_[menuType].push_back(new MvQMenuItem(actionForward_));
    menuItems_[menuType].push_back(new MvQMenuItem(sep, MvQMenuItem::MenuTarget));
    menuItems_[menuType].push_back(new MvQMenuItem(actionHome_));
}

void MvQHelpBrowser::setupHelpActions()
{
    // About
    QAction* actionAbout = new QAction(this);
    actionAbout->setObjectName(QString::fromUtf8("actionAbout"));
    QIcon icon;
    icon.addPixmap(QPixmap(MvQTheme::logo()), QIcon::Normal, QIcon::Off);
    actionAbout->setIcon(icon);
    actionAbout->setText(tr("&About HelpBrowser"));

    connect(actionAbout, SIGNAL(triggered()), this, SLOT(slotShowAboutBox()));

    MvQMainWindow::MenuType menuType = MvQMainWindow::HelpMenu;

    menuItems_[menuType].push_back(new MvQMenuItem(actionAbout, MvQMenuItem::MenuTarget));
}

void MvQHelpBrowser::docHome()
{
    webView_->load(QUrl("qthelp://int.wcmwf.metview.userguide/doc/METV/index.html"));
}

void MvQHelpBrowser::setWebSource(const QUrl& url)
{
    // qDebug() << "setWebSource url=" << url.toString();
    if (url.scheme() == "qthelp")
        webView_->load(url);
    else
        QDesktopServices::openUrl(url);
    // for(int i=0; i < webView_->history()->count(); i++) qDebug() << "item" << i << webView_->history()->itemAt(i).url();
}

void MvQHelpBrowser::writeSettings()
{
    QSettings settings(MVQ_QSETTINGS_DEFAULT_ARGS, "MV4-HelpBrowser");

    settings.clear();

    settings.beginGroup("mainWindow");
    settings.setValue("geometry", saveGeometry());
    settings.setValue("splitter", splitter_->saveState());
    settings.endGroup();
}

void MvQHelpBrowser::readSettings()
{
    QSettings settings(MVQ_QSETTINGS_DEFAULT_ARGS, "MV4-HelpBrowser");

    settings.beginGroup("mainWindow");
    restoreGeometry(settings.value("geometry").toByteArray());
    splitter_->restoreState(settings.value("splitter").toByteArray());
    settings.endGroup();
}

///////////////////////////////////////
//#include "MvHelpNetworkAccessManager.h"
#include <QByteArray>
#include <QHelpEngine>
#include <QIODevice>
#include <QNetworkAccessManager>
#include <QNetworkProxy>
#include <QPointer>
#include <QTimer>
#include <QNetworkReply>

MvHelpNetworkReply::MvHelpNetworkReply(const QUrl& url, QHelpEngineCore* help_engine) :
    QNetworkReply(help_engine)
{
    Q_ASSERT(help_engine);

    d_help_engine = help_engine;
    setUrl(url);
    QTimer::singleShot(0, this, SLOT(process()));
}

void MvHelpNetworkReply::process()
{
    if (d_help_engine) {
        QByteArray rawData = d_help_engine->fileData(url());
        d_buffer.setData(rawData);
        d_buffer.open(QIODevice::ReadOnly);

        open(QIODevice::ReadOnly | QIODevice::Unbuffered);
        setHeader(QNetworkRequest::ContentLengthHeader, QVariant(rawData.size()));
        setHeader(QNetworkRequest::ContentTypeHeader, "text/html");
        emit readyRead();
        emit finished();
    }
}
