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

 Copyright 2014 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 "OutputBrowser.h"

#include <QVBoxLayout>

//#include "Highlighter.hpp"
#include "MessageLabel.h"
#include "PlainTextEdit.h"
#include "PlainTextSearchInterface.h"
#include "TextEditSearchLine.h"
#include "TextPagerSearchInterface.hpp"
#include "TextPagerWidget.hpp"

int OutputBrowser::minPagerTextSize_ = 1 * 1024 * 1024;
int OutputBrowser::minPagerSparseSize_ = 30 * 1024 * 1024;
int OutputBrowser::minConfirmSearchSize_ = 5 * 1024 * 1024;

OutputBrowser::OutputBrowser(QWidget* parent) :
    QWidget(parent),
    lastPos_(0)
{
    QVBoxLayout* vb = new QVBoxLayout(this);
    vb->setContentsMargins(0, 0, 0, 0);
    vb->setSpacing(2);

    stacked_ = new QStackedWidget(this);
    vb->addWidget(stacked_, 1);

    confirmSearchLabel_ = new MessageLabel(this);
    confirmSearchLabel_->setShowTypeTitle(false);
    confirmSearchLabel_->setNarrowMode(true);
    vb->addWidget(confirmSearchLabel_);

    searchLine_ = new TextEditSearchLine(this);
    vb->addWidget(searchLine_);

    // Basic textedit
    textEdit_ = new PlainTextEdit(this);
    textEdit_->setReadOnly(true);
    textEdit_->setWordWrapMode(QTextOption::NoWrap);

    textEditSearchInterface_ = new PlainTextSearchInterface();
    textEditSearchInterface_->setEditor(textEdit_);

    // This highlighter only works for jobs
#if 0
    jobHighlighter_=new Highlighter(textEdit_->document(),"job");
    jobHighlighter_->setDocument(nullptr);
#endif
    // Pager for very large files
    textPager_ = new TextPagerWidget(this);
    // textEdit_->setReadOnly(true);

    textPagerSearchInterface_ = new TextPagerSearchInterface();
    textPagerSearchInterface_->setEditor(textPager_->textEditor());

    stacked_->addWidget(textEdit_);
    stacked_->addWidget(textPager_);

    stacked_->setCurrentIndex(BasicIndex);
    searchLine_->hide();

    connect(searchLine_, SIGNAL(visibilityChanged()),
            this, SLOT(showConfirmSearchLabel()));
}

OutputBrowser::~OutputBrowser()
{
    delete textEditSearchInterface_;
    delete textPagerSearchInterface_;

#if 0
    if(jobHighlighter_ && !jobHighlighter_->parent())
    {
            delete jobHighlighter_;
    }
#endif
}

void OutputBrowser::clear()
{
    if (stacked_->currentIndex() == BasicIndex)
        cursorCache_[currentSourceFile_].pos_ = textEdit_->textCursor().position();
    else
        cursorCache_[currentSourceFile_].pos_ = textPager_->textEditor()->textCursor().position();

    currentSourceFile_.clear();

    textEdit_->clear();
    textPager_->clear();
#if 0
    file_.reset();
#endif
}

void OutputBrowser::changeIndex(IndexType indexType, qint64 fileSize)
{
    if (indexType == BasicIndex) {
        stacked_->setCurrentIndex(indexType);
        searchLine_->setConfirmSearch(false);
        searchLine_->setSearchInterface(textEditSearchInterface_);
        // confirmSearchLabel_->clear();
        // confirmSearchLabel_->hide();

        textPager_->clear();
    }
    else {
        stacked_->setCurrentIndex(indexType);
        searchLine_->setConfirmSearch(fileSize >= minConfirmSearchSize_);
        searchLine_->setSearchInterface(textPagerSearchInterface_);
        // confirmSearchLabel_->show();
        // confirmSearchLabel_->showWarning(searchLine_->confirmSearchText());
        textEdit_->clear();
    }

    showConfirmSearchLabel();
}

#if 0
void OutputBrowser::loadFile(VFile_ptr file)
{
    if(!file)
    {
        clear();
        return;
    }

    file_=file;
    if(file_->storageMode() == VFile::DiskStorage)
    {
        loadFile(QString::fromStdString(file_->path()));

        //Set the cursor position from the cache
        updateCursorFromCache(file_->sourcePath());
    }
    else
    {
        QString s(file_->data());
        loadText(s,QString::fromStdString(file_->sourcePath()),true);
    }
}
#endif

void OutputBrowser::loadFile(QString fileName)
{
    QFile file(fileName);
    file.open(QIODevice::ReadOnly);
    QFileInfo fInfo(file);
    qint64 fSize = fInfo.size();

    if (!isJobFile(fileName) && fSize >= minPagerTextSize_) {
        changeIndex(PagerIndex, fSize);

        TextPagerDocument::DeviceMode mode = (fSize >= minPagerSparseSize_) ? TextPagerDocument::Sparse : TextPagerDocument::LoadAll;
        textPager_->load(fileName, mode);
    }
    else {
        changeIndex(BasicIndex, fSize);

        adjustHighlighter(fileName);

        QString str = file.readAll();
        textEdit_->document()->setPlainText(str);
    }
}

void OutputBrowser::loadText(QString txt, QString fileName, bool resetFile)
{
#if 0
    if(resetFile)
       file_.reset();
#endif

    // We estimate the size in bytes
    qint64 txtSize = txt.size() * 2;

    if (!isJobFile(fileName) && txtSize > minPagerTextSize_) {
        changeIndex(PagerIndex, txtSize);
        textPager_->setText(txt);
    }
    else {
        changeIndex(BasicIndex, txtSize);
        adjustHighlighter(fileName);
        textEdit_->document()->setPlainText(txt);
    }

    // Set the cursor position from the cache
    updateCursorFromCache(fileName.toStdString());
}

void OutputBrowser::updateCursorFromCache(const std::string& sourcePath)
{
#if 0
    //Set the cursor position from the cache
    QMap<std::string,CursorCacheItem>::const_iterator it=cursorCache_.find(sourcePath);
    if(it != cursorCache_.end())
    {
        setCursorPos(it.value().pos_);
    }
    currentSourceFile_=file_->sourcePath();
#endif
}

bool OutputBrowser::isJobFile(QString fileName)
{
    return fileName.contains(".job");
}

void OutputBrowser::adjustHighlighter(QString fileName)
{
#if 0
    //For job files we set the proper highlighter
    if(isJobFile(fileName))
    {
	if(!jobHighlighter_)
	{
            jobHighlighter_=new Highlighter(textEdit_->document(),"job");
	}
	else if(jobHighlighter_->document() != textEdit_->document())
	{
            jobHighlighter_->setDocument(textEdit_->document());
	}
    }
    else if(jobHighlighter_)
    {
	jobHighlighter_->setDocument(nullptr);
    }
#endif
}

void OutputBrowser::gotoLine()
{
    if (stacked_->currentIndex() == BasicIndex)
        textEdit_->gotoLine();
    else
        textPager_->gotoLine();
}

void OutputBrowser::showSearchLine()
{
    searchLine_->setVisible(true);
    searchLine_->setFocus();
    searchLine_->selectAll();
}

void OutputBrowser::searchOnReload(bool userClickedReload)
{
    searchLine_->searchOnReload(userClickedReload);
}

void OutputBrowser::setFontProperty(MvQProperty* p)
{
    textEdit_->setFontProperty(p);
    textPager_->setFontProperty(p);
}

void OutputBrowser::updateFont()
{
    textEdit_->updateFont();
}

void OutputBrowser::zoomIn()
{
    textEdit_->slotZoomIn();
    textPager_->zoomIn();
}

void OutputBrowser::zoomOut()
{
    textEdit_->slotZoomOut();
    textPager_->zoomOut();
}

void OutputBrowser::showConfirmSearchLabel()
{
    if (searchLine_->isVisible() && searchLine_->confirmSearch()) {
        confirmSearchLabel_->showWarning(searchLine_->confirmSearchText());
        // confirmSearchLabel_->show();
    }
    else {
        confirmSearchLabel_->hide();
    }
}

void OutputBrowser::setCursorPos(qint64 pos)
{
    if (stacked_->currentIndex() == BasicIndex) {
        QTextCursor c = textEdit_->textCursor();
        c.setPosition(pos);
        textEdit_->setTextCursor(c);
    }
    else {
        textPager_->textEditor()->setCursorPosition(pos);
    }
}
