/*
 Overview GUI Implementation
 Copyright (c)2011 Mark Watkins <jedimark@users.sourceforge.net>
 License: GPL
*/

#include <QCalendarWidget>
#include <QTextCharFormat>
#include <QSystemLocale>
#include <QDebug>
#include <QDateTimeEdit>
#include <QCalendarWidget>
#include <QFileDialog>
#include "SleepLib/profiles.h"
#include "overview.h"
#include "ui_overview.h"
#include "common_gui.h"
#include "Graphs/gXAxis.h"
#include "Graphs/gLineChart.h"
#include "Graphs/gYAxis.h"

Overview::Overview(QWidget *parent,gGraphView * shared) :
    QWidget(parent),
    ui(new Ui::Overview),
    m_shared(shared)
{
    ui->setupUi(this);

    // Set Date controls locale to 4 digit years
    QLocale locale=QLocale::system();
    QString shortformat=locale.dateFormat(QLocale::ShortFormat);
    if (!shortformat.toLower().contains("yyyy")) {
        shortformat.replace("yy","yyyy");
    }
    ui->dateStart->setDisplayFormat(shortformat);
    ui->dateEnd->setDisplayFormat(shortformat);

    Qt::DayOfWeek dow=firstDayOfWeekFromLocale();

    ui->dateStart->calendarWidget()->setFirstDayOfWeek(dow);
    ui->dateEnd->calendarWidget()->setFirstDayOfWeek(dow);


    // Stop both calendar drop downs highlighting weekends in red
    QTextCharFormat format = ui->dateStart->calendarWidget()->weekdayTextFormat(Qt::Saturday);
    format.setForeground(QBrush(Qt::black, Qt::SolidPattern));
    ui->dateStart->calendarWidget()->setWeekdayTextFormat(Qt::Saturday, format);
    ui->dateStart->calendarWidget()->setWeekdayTextFormat(Qt::Sunday, format);
    ui->dateEnd->calendarWidget()->setWeekdayTextFormat(Qt::Saturday, format);
    ui->dateEnd->calendarWidget()->setWeekdayTextFormat(Qt::Sunday, format);

    // Connect the signals to update which days have CPAP data when the month is changed
    connect(ui->dateStart->calendarWidget(),SIGNAL(currentPageChanged(int,int)),SLOT(dateStart_currentPageChanged(int,int)));
    connect(ui->dateEnd->calendarWidget(),SIGNAL(currentPageChanged(int,int)),SLOT(dateEnd_currentPageChanged(int,int)));

    // Create the horizontal layout to hold the GraphView object and it's scrollbar
    layout=new QHBoxLayout(ui->graphArea);
    layout->setSpacing(0); // remove the ugly margins/spacing
    layout->setMargin(0);
    layout->setContentsMargins(0,0,0,0);
    ui->graphArea->setLayout(layout);
    ui->graphArea->setAutoFillBackground(false);

    // Create the GraphView Object
    GraphView=new gGraphView(ui->graphArea,m_shared);
    GraphView->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);

    // Create the custom scrollbar and attach to GraphView
    scrollbar=new MyScrollBar(ui->graphArea);
    scrollbar->setOrientation(Qt::Vertical);
    scrollbar->setSizePolicy(QSizePolicy::Maximum,QSizePolicy::Expanding);
    scrollbar->setMaximumWidth(20);
    GraphView->setScrollBar(scrollbar);

    // Add the graphView and scrollbar to the layout.
    layout->addWidget(GraphView,1);
    layout->addWidget(scrollbar,0);
    layout->layout();

    // TODO: Automate graph creation process

    // The following code (to the closing marker) is crap --->
    AHI=createGraph("AHI");
    UC=createGraph("Usage");
    PR=createGraph("Pressure");
    SET=createGraph("Settings");
    LK=createGraph("Leaks");
    SES=createGraph("Sessions");
    NPB=createGraph("% in PB");
    RR=createGraph("Resp. Rate");

    uc=new SummaryChart("Hours",GT_BAR);
    uc->addSlice("",QColor("green"),ST_HOURS);
    UC->AddLayer(uc);

    ses=new SummaryChart("Sessions",GT_LINE);
    ses->addSlice("",QColor("blue"),ST_SESSIONS);
    SES->AddLayer(ses);

    bc=new SummaryChart("AHI",GT_BAR);
    bc->addSlice(CPAP_Hypopnea,QColor("blue"),ST_CPH);
    bc->addSlice(CPAP_Apnea,QColor("dark green"),ST_CPH);
    bc->addSlice(CPAP_Obstructive,QColor("#40c0ff"),ST_CPH);
    bc->addSlice(CPAP_ClearAirway,QColor("purple"),ST_CPH);
    AHI->AddLayer(bc);

    set=new SummaryChart("",GT_LINE);
    //set->addSlice("SysOneResistSet",QColor("grey"),ST_SETAVG);
    set->addSlice("HumidSet",QColor("blue"),ST_SETWAVG);
    set->addSlice("FlexSet",QColor("red"),ST_SETWAVG);
    //set->addSlice("PAPMode",QColor("red"),ST_SETAVG);
    SET->setRecMinY(0);
    SET->setRecMaxY(5);
    SET->AddLayer(set);

    rr=new SummaryChart("bpm",GT_LINE);
    rr->addSlice(CPAP_RespRate,QColor("light blue"),ST_MIN);
    rr->addSlice(CPAP_RespRate,QColor("light green"),ST_90P);
    rr->addSlice(CPAP_RespRate,QColor("blue"),ST_WAVG);
    RR->AddLayer(rr);

    pr=new SummaryChart("cmH2O",GT_LINE);
    //PR->setRecMinY(4.0);
    //PR->setRecMaxY(12.0);
    pr->addSlice(CPAP_Pressure,QColor("dark green"),ST_WAVG);
    pr->addSlice(CPAP_Pressure,QColor("orange"),ST_MIN);
    pr->addSlice(CPAP_Pressure,QColor("red"),ST_MAX);
    pr->addSlice(CPAP_Pressure,QColor("grey"),ST_90P);
    pr->addSlice(CPAP_EPAP,QColor("light green"),ST_MIN);
    pr->addSlice(CPAP_IPAP,QColor("light blue"),ST_MAX);
    PR->AddLayer(pr);

    lk=new SummaryChart("Avg Leak",GT_LINE);
    lk->addSlice(CPAP_Leak,QColor("dark grey"),ST_90P);
    lk->addSlice(CPAP_Leak,QColor("dark blue"),ST_WAVG);
    //lk->addSlice(CPAP_Leak,QColor("dark yellow"));
    //pr->addSlice(CPAP_IPAP,QColor("red"));
    LK->AddLayer(lk);

    NPB->AddLayer(npb=new SummaryChart("% PB",GT_BAR));
    npb->addSlice(CPAP_CSR,QColor("light green"),ST_SPH);
    // <--- The code to the previous marker is crap

    report=NULL;

    GraphView->LoadSettings("Overview");
}
Overview::~Overview()
{
    GraphView->SaveSettings("Overview");
    disconnect(this,SLOT(dateStart_currentPageChanged(int,int)));
    disconnect(this,SLOT(dateEnd_currentPageChanged(int,int)));
    if (report) {
        report->close();
        delete report;
    }
    delete ui;
}
gGraph * Overview::createGraph(QString name)
{
    gGraph *g=new gGraph(GraphView,name,default_height,0);
    g->AddLayer(new gYAxis(),LayerLeft,gYAxis::Margin);
    gXAxis *x=new gXAxis();
    x->setUtcFix(true);
    g->AddLayer(x,LayerBottom,0,gXAxis::Margin);
    g->AddLayer(new gXGrid());
    return g;
}

void Overview::ReloadGraphs()
{
    ui->dateStart->setDate(p_profile->FirstDay());
    ui->dateEnd->setDate(p_profile->LastDay());
    GraphView->setDay(NULL);

}

void Overview::RedrawGraphs()
{
    GraphView->updateGL();
}

void Overview::UpdateCalendarDay(QDateEdit * dateedit,QDate date)
{
    QCalendarWidget *calendar=dateedit->calendarWidget();
    QTextCharFormat bold;
    QTextCharFormat cpapcol;
    QTextCharFormat normal;
    QTextCharFormat oxiday;
    bold.setFontWeight(QFont::Bold);
    cpapcol.setForeground(QBrush(Qt::blue, Qt::SolidPattern));
    cpapcol.setFontWeight(QFont::Bold);
    oxiday.setForeground(QBrush(Qt::red, Qt::SolidPattern));
    oxiday.setFontWeight(QFont::Bold);
    bool hascpap=p_profile->GetDay(date,MT_CPAP)!=NULL;
    bool hasoxi=p_profile->GetDay(date,MT_OXIMETER)!=NULL;
    //bool hasjournal=p_profile->GetDay(date,MT_JOURNAL)!=NULL;

    if (hascpap) {
        if (hasoxi) {
            calendar->setDateTextFormat(date,oxiday);
        } else {
            calendar->setDateTextFormat(date,cpapcol);
        }
    } else if (p_profile->GetDay(date)) {
        calendar->setDateTextFormat(date,bold);
    } else {
        calendar->setDateTextFormat(date,normal);
    }
    calendar->setHorizontalHeaderFormat(QCalendarWidget::ShortDayNames);
}
void Overview::dateStart_currentPageChanged(int year, int month)
{
    QDate d(year,month,1);
    int dom=d.daysInMonth();

    for (int i=1;i<=dom;i++) {
        d=QDate(year,month,i);
        UpdateCalendarDay(ui->dateStart,d);
    }
}
void Overview::dateEnd_currentPageChanged(int year, int month)
{
    QDate d(year,month,1);
    int dom=d.daysInMonth();

    for (int i=1;i<=dom;i++) {
        d=QDate(year,month,i);
        UpdateCalendarDay(ui->dateEnd,d);
    }
}


void Overview::on_dateEnd_dateChanged(const QDate &date)
{
    qint64 d1=qint64(QDateTime(ui->dateStart->date(),QTime(0,0,0),Qt::UTC).toTime_t())*1000L;
    qint64 d2=qint64(QDateTime(date,QTime(23,59,59),Qt::UTC).toTime_t())*1000L;
    GraphView->SetXBounds(d1,d2);

}

void Overview::on_dateStart_dateChanged(const QDate &date)
{
    qint64 d1=qint64(QDateTime(date,QTime(0,0,0),Qt::UTC).toTime_t())*1000L;
    qint64 d2=qint64(QDateTime(ui->dateEnd->date(),QTime(23,59,59),Qt::UTC).toTime_t())*1000L;
    GraphView->SetXBounds(d1,d2);

}

void Overview::on_toolButton_clicked()
{
    qint64 d1=qint64(QDateTime(ui->dateStart->date(),QTime(0,0,0),Qt::UTC).toTime_t())*1000L;
    qint64 d2=qint64(QDateTime(ui->dateEnd->date(),QTime(23,59,59),Qt::UTC).toTime_t())*1000L;
    GraphView->SetXBounds(d1,d2);
}

QString Overview::GetHTML()
{
    if (!report) {
        report=new Report(this,m_shared,this);
        report->hide();
    }

    QString html;
    if (report) {
        GraphView->deselect();

        report->ReloadGraphs();
        QString reportname="overview";
        html=report->GenerateReport(reportname,ui->dateStart->date(),ui->dateEnd->date());
        if (html.isEmpty()) {
            qDebug() << "Faulty Report" << reportname;
        }
    }
    return html;
}
void Overview::on_printButton_clicked()
{
    report->Print(GetHTML());
}

void Overview::on_htmlButton_clicked()
{
    QString html=GetHTML();
    QString filename=QFileDialog::getSaveFileName(this,tr("Save HTML Report"),PREF.Get("{home}"),tr("HTML Documents (*.html)"));
    if (!filename.isEmpty()) {
        QFile file(filename);
        file.open(QIODevice::WriteOnly);
        QByteArray ba;
        ba.append(html);
        file.write(ba);
        file.close();
    }

}
void Overview::ResetGraphLayout()
{
    GraphView->resetLayout();
}