/***************************************************************************
              exporteyepieceview.cpp  -  K Desktop Planetarium
                             -------------------
    begin                : Sun 17 Jan 2016 21:35:49 CST
    copyright            : (c) 2016 by Akarsh Simha
    email                : akarsh@kde.org
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/


/* Project Includes */
#include "exporteyepieceview.h"
#include "eyepiecefield.h"
#include "skypoint.h"
#include "kstarsdatetime.h"
#include "dms.h"
#include "kstarsdata.h"
#include "Options.h"

/* KDE Includes */

/* Qt Includes */
#include <QWidget>
#include <QComboBox>
#include <QPixmap>
#include <QDialogButtonBox>
#include <QPainter>
#include <QFileDialog>

ExportEyepieceView::ExportEyepieceView( const SkyPoint *_sp, const KStarsDateTime &dt, const QPixmap *renderImage, const QPixmap *renderChart,
                                        QWidget *parent ) : QDialog( parent ), m_dt( dt ) {
    m_sp = new SkyPoint( *_sp ); // Work on a copy.

    Q_ASSERT( renderChart );
    m_renderChart = new QPixmap( *renderChart );

    if( renderImage )
        m_renderImage = new QPixmap( *renderImage );
    else
        m_renderImage = 0;

    setWindowTitle( i18n( "Export eyepiece view" ) );

    QWidget *mainWidget = new QWidget( this );
    QVBoxLayout *mainLayout = new QVBoxLayout;
    mainLayout->addWidget(mainWidget);
    setLayout(mainLayout);

    QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Save | QDialogButtonBox::Cancel);
    mainLayout->addWidget(buttonBox);
    connect(buttonBox, SIGNAL(rejected()), this, SLOT(slotCloseDialog()));
    connect(buttonBox, SIGNAL(accepted()), this, SLOT(slotSaveImage()));

    QVBoxLayout *rows = new QVBoxLayout;
    mainWidget->setLayout( rows );

    QLabel *tickInfoLabel = new QLabel( i18n( "Overlay orientation vs. time ticks: " ), this );
    m_tickConfigCombo = new QComboBox( this );
    m_tickConfigCombo->addItem( i18n( "None" ) );
    m_tickConfigCombo->addItem( i18n( "Towards Zenith" ) );
    m_tickConfigCombo->addItem( i18n( "Dobsonian View" ) );

    QHBoxLayout *optionsLayout = new QHBoxLayout;
    optionsLayout->addWidget( tickInfoLabel );
    optionsLayout->addWidget( m_tickConfigCombo );
    optionsLayout->addStretch();
    rows->addLayout( optionsLayout );

    m_tickWarningLabel = new QLabel( this );
    rows->addWidget( m_tickWarningLabel );

    m_outputDisplay = new QLabel;
    m_outputDisplay->setBackgroundRole( QPalette::Base );
    m_outputDisplay->setScaledContents( false );
    m_outputDisplay->setMinimumWidth( 400 );
    m_outputDisplay->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Expanding );
    rows->addWidget( m_outputDisplay );

    connect( m_tickConfigCombo, SIGNAL( currentIndexChanged( int ) ), this, SLOT( slotOverlayTicks( int ) ) );
    connect( m_tickConfigCombo, SIGNAL( activated( int ) ), this, SLOT( slotOverlayTicks( int ) ) );

    render();
    show();
}

ExportEyepieceView::~ExportEyepieceView() {
    delete m_sp;
    delete m_renderChart;
    delete m_renderImage;
}

void ExportEyepieceView::slotOverlayTicks( int tickConfig ) {
    m_tickConfig = tickConfig;
    if( tickConfig == 0 )
        m_tickWarningLabel->setText( QString() );
    else if( tickConfig == 1 )
        m_tickWarningLabel->setText( i18n( "Note: This overlay makes sense only if the view was generated in alt/az mode with a preset such as Refractor or Vanilla" ) );
    else if( tickConfig == 2 )
        m_tickWarningLabel->setText( i18n( "Note: This overlay  makes sense only if the view was generated in alt/az mode with a preset such as Dobsonian" ) );
    render();
}

void ExportEyepieceView::render() {
    float baseWidth = m_renderChart->width();
    float baseHeight = m_renderChart->height();

    if( m_renderImage )
        m_output = QImage( int(baseWidth * 2.25), int(baseHeight), QImage::Format_ARGB32 ); // 0.25 * baseWidth gap between the images
    else
        m_output = QImage( int(baseWidth), int(baseHeight), QImage::Format_ARGB32 );

    m_output.fill( Qt::white );
    QPainter op( &m_output );
    op.drawPixmap( QPointF(0,0), *m_renderChart );
    if( m_renderImage )
        op.drawPixmap( QPointF(baseWidth * 1.25,0), *m_renderImage );

    if( m_tickConfig != 0 && Options::useAltAz() ) { // FIXME: this is very skymap-state-heavy for my happiness --asimha
        // we must draw ticks
        QImage tickOverlay( baseWidth, baseHeight, QImage::Format_ARGB32 );
        tickOverlay.fill( Qt::transparent );

        QPainter p( &tickOverlay );
        p.setPen( Qt::red ); // FIXME: Determine color depending on situation, or make it configurable
        double rEnd = 0.85 * ( baseWidth / 2.);
        double rStart = 0.8 * ( baseWidth / 2.);
        QFont font;
        font.setPixelSize( ( rEnd - rStart ) );
        p.setFont( font );

        GeoLocation *geo = KStarsData::Instance()->geo();
        double alt0 = m_sp->alt().Degrees(); // altitude when hour = 0, i.e. at m_dt (see below).
        dms northAngle0 = EyepieceField::findNorthAngle( m_sp, geo->lat() );

        for( float hour = -3.5; hour <= 3.5; hour += 0.5 ) {
            dms rotation; // rotation

            // FIXME: Code duplication : code duplicated from EyepieceField. This should really be a member of SkyPoint or something.
            SkyPoint sp = SkyPoint::timeTransformed( m_sp, m_dt, geo, hour );
            double alt = sp.alt().Degrees();
            dms northAngle = EyepieceField::findNorthAngle( &sp, geo->lat() );

            rotation = ( northAngle - northAngle0 );
            if( m_tickConfig == 2 ) {
                // Dobsonian: add additional CW rotation by altitude, but compensate for the fact that we've already rotated by alt0
                rotation = rotation - dms( ( alt - alt0 ) );
            }
            rotation = rotation.reduce();
            p.save();
            p.translate( baseWidth/2.0, baseHeight/2.0 );
            p.rotate( -( rotation.Degrees() + 90.0 ) );
            p.drawLine( QPointF( rStart, 0 ), QPointF( rEnd, 0 ) );
            QTime ct = geo->UTtoLT( m_dt.addSecs( 3600.0 * hour ) ).time();
            p.drawText( QPointF( rEnd + 0.01 * baseWidth, 0 ), QString().sprintf( "%02d:%02d", ct.hour(), ct.minute() ) );
            p.restore();
        }
        p.end();
        op.drawImage( QPointF(0,0), tickOverlay );
        if( m_renderImage ) {
            op.drawImage( QPointF(baseWidth * 1.25, 0), tickOverlay );
        }
    }
    op.end();

    m_outputDisplay->setPixmap( (QPixmap::fromImage( m_output )).scaled( m_outputDisplay->width(), m_outputDisplay->height(), Qt::KeepAspectRatio, Qt::SmoothTransformation ) );
}

void ExportEyepieceView::slotSaveImage() {
    // does nothing at the moment. TODO: Implement.
    QString fileName = QFileDialog::getSaveFileName( this, i18n("Save image as"), QString(), i18n( "Image files (*.png *.jpg *.xpm *.bmp *.gif)" ) );
    if( !fileName.isEmpty() ) {
        m_output.save( fileName );
        slotCloseDialog();
    }
}

void ExportEyepieceView::slotCloseDialog() {
    hide();
    deleteLater();
}
