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

 Copyright 2016 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 "BufrKeyWidget.h"

#include "MvQBufrDataItem.h"
#include "MvEccBufr.h"
#include "MvQKeyProfileModel.h"
#include "MvKeyProfile.h"

#include <QTreeWidgetItem>

static QColor textCol(50,50,50);

BufrKeyWidget::BufrKeyWidget(QWidget *parent) : QWidget(parent)
{
    setupUi(this);

    te_->setReadOnly(true);

    model_= new MvQKeyProfileModel(this);
    model_->setShadeFirstColumn(true);

    sortModel_= new MvQKeyProfileSortFilterModel(this);
    sortModel_->setSourceModel(model_);
    sortModel_->setDynamicSortFilter(true);
    sortModel_->setFilterRole(Qt::UserRole);
    sortModel_->setFilterFixedString("1");
    sortModel_->setFilterKeyColumn(0);

    tree_->setModels(model_,sortModel_);
    tree_->setUniformRowHeights(true);
    tree_->setAlternatingRowColors(false);
    tree_->hide();

    //Set css for the text formatting
    QString cssDoc="td {padding-left: 3px; paddig-top: 1px; padding-bottom: 1px; background-color: #F3F3F3;color: #000000;} \
                    td.title {padding-left: 2px; padding-top: 1px; padding-bottom: 1px;background-color: #e3e6f3; color: #000000;}";


    te_->document()->setDefaultStyleSheet(cssDoc);
}

void BufrKeyWidget::clear()
{
    te_->clear();
    model_->clear();
    tree_->hide();
}

//Subset is indexed from 0 here!!!!
void BufrKeyWidget::setData(MvQBufrDataItem* item,int subset,MvEccBufrMessage* ecc)
{
    te_->clear();
    model_->clear();
    tree_->hide();

    if(!item)
        return;

    QString tp;
    QString key=item->key();
    QString value=item->value(subset);
    QString units=item->data("units");
    QString element =item->data("code");
    QString index=item->data("index");
    int bitWidth =item->data("width").toInt();

    if(key.isEmpty())
        return;

    tp="<table width=\'100%\'>";

    //Key block
    tp+=formatRow("key",key);
    if(!index.isEmpty())
        tp+=formatRow("index",index);

    //Value block
    tp+="<tr><td class=\'title\' colspan=\'2\' align=\'center\'>Value</td></tr>";
    tp+=formatRow("value",value);
    if(!units.isEmpty())
    {
        tp+=formatRow("units",units);
        if(value != "missing")
        {
            if(units == "CODE TABLE")
            {
                if(MvBufrCodeTable* table=MvBufrCodeTable::find(element.toInt(),ecc))
                {
                    const std::string& v=table->value(value.toInt());                    
                    tp+=formatRow("code text",QString::fromStdString(v));
                }
            }
            else if(units == "FLAG TABLE")
            {
                if(MvBufrFlagTable* table=MvBufrFlagTable::find(element.toInt(),ecc))
                {
                    MvBufrFlagInfo flags;
                    table->values(value.toInt(),bitWidth,flags);
                    if(flags.bits().empty() == false)
                    {                      
                        tp+=formatRow("bits",QString::fromStdString(flags.bits()));
                        for(int i=0; i < flags.num(); i++)
                        {
                            tp+=formatRow("flag[" + QString::fromStdString(flags.bitPosition(i)) + "]",
                                      QString::fromStdString(flags.description(i)));
                        }
                    }
                }
            }
        }
    }


    //Element block
    if(!element.isEmpty())
    {
        tp+="<tr><td class=\'title\' colspan=\'2\' align=\'center\'>Element</td></tr>";
        tp+=formatElementBlock(element);

        //Scale etc
        tp+="<tr><td class=\'title\' colspan=\'2\' align=\'center\'>Representation</td></tr>";
        tp+=formatRow("scale",item->data("scale"));
        tp+=formatRow("reference",item->data("reference"));
        tp+=formatRow("width",item->data("width"));

        QString eccType="double";
        QString unitsUpper=units.toUpper();
        if(unitsUpper.startsWith("CCITT") ||
           unitsUpper.startsWith("CHARACTER"))
            eccType="string";
        else if(unitsUpper.contains("CODE TABLE"))
            eccType="CODE TABLE";
        else if(unitsUpper.startsWith("FLAG TABLE"))
            eccType="FLAG TABLE";
        else if(item->data("scale").toInt() <= 0)
            eccType="long";
        tp+=formatRow("type",eccType);
    }

    tp+="</table>";
    te_->insertHtml(tp);

    //Display array values in tree
    if(item->valueIsArray() ||
      (key == "unexpandedDescriptors" && item->valueArray().count() > 1))
    {     
        int n=item->valueArray().count();
        if(n > 0)
        {
            MvKeyProfile *prof=new MvKeyProfile("tmp");
            std::string firstName=(key == "unexpandedDescriptors")?"pos":"subset";
            std::string secondName=(key == "unexpandedDescriptors")?"descriptor":"value";
            MvKey *firstKey=new MvKey(firstName,firstName);
            firstKey->setValueType(MvKey::IntType);
            firstKey->setIntRange(1,n);
            prof->addKey(firstKey);
            MvKey *secondKey=new MvKey(secondName,secondName);
            secondKey->setValueType(MvKey::StringType);
            prof->addKey(secondKey);

            for(int i = 0; i < n; ++i)
            {
                secondKey->addValue(item->valueArray()[i].toStdString());
            }

            model_->setKeyProfile(prof);

            tree_->show();
            tree_->resizeColumnToContents(0);

            //subset is indexed from 0 here
            if(key != "unexpandedDescriptors" && subset >=0 && subset< n)
                tree_->setCurrentIndex(model_->index(subset,0));
        }
    }

}

QString BufrKeyWidget::formatKey(QString key)
{
     return "<b><font color=\'" + textCol.name() + "\'>" + key + "</font></b>: ";
}

QString BufrKeyWidget::formatValue(QString val)
{
     return "<font color=\'" + textCol.name() + "\'>" + val + "</font>";
}

QString BufrKeyWidget::formatRow(QString key,QString val)
{
     QString s="<tr><td>" + formatKey(key) + "</td><td>" + formatValue(val) + "</td></tr>";
     return s;
}

QString BufrKeyWidget::formatElementBlock(QString val)
{
    QString s;
    QString key("element");
    if(val.length() == 6)
    {
        QString type=val.mid(0,1);
        QString cat=val.mid(1,2);
        QString code=val.mid(3,3);

        QString defType="???";
        switch(MvEccBufr::elementDefType(val.toInt()))
        {
        case MvEccBufr::WmoElement:
            defType="WMO";
            break;
        case MvEccBufr::LocalElement:
            defType="local";
            break;
        default:
            break;
        }

        QColor typeCol(60,60,0);
        QColor catCol(140,76,129);
        QColor codeCol(76,100,140);

        QString typeStr="<b><font color=\'" + typeCol.name() + "\'>" + type + "</font></b>";
        QString catStr="<b><font color=\'" + catCol.name() + "\'>" + cat + "</font></b>";
        QString codeStr="<b><font color=\'" + codeCol.name() + "\'>" + code + "</font></b>";

        s+=formatRow(key,typeStr + catStr + codeStr);
        s+=formatRow("category",catStr);
        s+=formatRow("code",codeStr);
        s+=formatRow("definition",defType);
    }
    else
    {
        s=formatRow(key,val);
    }
    return s;
}

