/***************************************************************************
 *   Copyright (C) 2019 by Santiago González                               *
 *                                                                         *
 ***( see copyright.txt file at root folder )*******************************/

#include <QMenu>
#include <QMovie>
#include <QFileDialog>
#include <QPainter>
#include <QDebug>

#include "image.h"
#include "circuit.h"
#include "itemlibrary.h"
#include "mainwindow.h"
#include "utils.h"

#include "stringprop.h"
#include "boolprop.h"

#define tr(str) simulideTr("Image",str)

Component* Image::construct( QString type, QString id )
{ return new Image( type, id ); }

LibraryItem* Image::libraryItem()
{
    return new LibraryItem(
        tr("Image"),
        "Graphical",
        "img.png",
        "Image",
        Image::construct);
}

Image::Image( QString type, QString id )
     : Shape( type, id )
{
    m_background = "";
    m_image = QPixmap( ":/saveimage.svg" );
    m_hSize = 80;
    m_vSize = 80;
    m_area = QRectF(-40,-40, 80, 80 );

    m_embeedBck = false;
    m_movie = nullptr;

    addProperty( tr("Main"),
        new BoolProp<Image>("Embeed_bck", tr("Embeed background"),""
                          , this, &Image::embeedBck, &Image::setEmbeedBck ) );

    addPropGroup( {"Hidden", {
        new StrProp<Image>("Image_File", tr("Image File"),""
                          , this, &Image::background, &Image::setBackground ),

        new StrProp<Image>("BckGndData", "",""
                          , this, &Image::bckGndData, &Image::setBckGndData )
    }, groupNoCopy | groupHidden} );
}
Image::~Image()
{
    if( m_movie ) delete m_movie;
}

void Image::contextMenu( QGraphicsSceneContextMenuEvent* event, QMenu* menu )
{
    QAction* loadAction = menu->addAction( QIcon(":/load.svg"),tr("Load Image") );
    QObject::connect( loadAction, &QAction::triggered, [=](){ slotLoad(); } );

    if( !m_bckGndData.isEmpty() ){
        QAction* saveAction = menu->addAction( QIcon(":/save.svg"),tr("Save Image") );
        QObject::connect( saveAction, &QAction::triggered, [=](){ slotSave(); } );
    }
    menu->addSeparator();
    Component::contextMenu( event, menu );
}

void Image::slotLoad()
{
    QString fil = m_background;
    if( fil.isEmpty() ) fil = Circuit::self()->getFilePath();

    const QString dir = fil;

    QString fileName = QFileDialog::getOpenFileName( 0l, tr("Load Image"), dir,
                       tr("All files (*.*)"));

    if( fileName.isEmpty() ) return; // User cancels loading

    setBackground( fileName );
    Shape::setHSize( m_image.width() );
    Shape::setVSize( m_image.height() );
}

void Image::slotSave()
{
    QString dir = Circuit::self()->getFilePath();
    QString fileName = QFileDialog::getSaveFileName( MainWindow::self(), tr("Save Image"), dir, "");
    if( fileName.isEmpty() ) return;

    m_image.save( fileName );
}

void Image::updateGif( const QRect &rect )
{
    m_image = m_movie->currentPixmap();
    update();
}

void Image::setBackground( QString bck )
{
    if( bck.isEmpty() ) return;

    QDir circuitDir = QFileInfo( Circuit::self()->getFilePath() ).absoluteDir();
    QString absPath = circuitDir.absoluteFilePath( bck );

    if( bck.endsWith(".gif") )
    {
        if( m_movie ) delete m_movie;

        m_movie = new QMovie( bck );
        /// FIXME: m_movie->setParent( this );

        if( m_movie->isValid() )
        {
            m_movie->setCacheMode( QMovie::CacheAll );
            QObject::connect( m_movie, &QMovie::updated, [=](const QRect &rect){ updateGif(rect); } );
            m_movie->start();
        }
        else qDebug() << "Image::setBackground : not a valid Gif animation";
    }

    if( bck.isEmpty() ) m_image = QPixmap( ":/saveimage.svg" );
    else{
        if( m_image.load( absPath ) ) m_background = absPath;
        else                          m_image = QPixmap( m_background );
        if( QFile::exists( m_background ) ){
            QByteArray ba = fileToByteArray( m_background, "Image::setBackground");
            QString bckData( ba.toHex() );
            m_bckGndData = bckData;
        }
    }
}

QString Image::background()
{
    QDir circuitDir = QFileInfo( Circuit::self()->getFilePath() ).absoluteDir();
    return circuitDir.relativeFilePath( m_background );
}

QString Image::bckGndData()
{
    if( !m_embeedBck ) return "";

    return m_bckGndData;
}

void Image::setBckGndData( QString data )
{
    m_bckGndData = data;

    if( data.isEmpty() ) return;

    QStringView dataRef{data};
    QByteArray ba;
    bool ok;
    for( int i=0; i<dataRef.size(); i+=2 )
    {
        QStringView ch = dataRef.mid( i, 2 );
        ba.append( ch.toInt( &ok, 16 ) );
    }
    m_image.loadFromData( ba );
    update();
}

void Image::paint( QPainter* p, const QStyleOptionGraphicsItem* o, QWidget* w )
{
    Component::paint( p, o, w );

    QPen pen( Qt::black, m_border, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
    p->setPen( pen );
    
    double opacity = p->opacity();
    p->setOpacity( opacity*m_opac );
    p->drawRect( m_area );
    p->setOpacity( opacity );

    p->drawPixmap( m_area, m_image, m_image.rect() );

    if( m_border > 0 )
    {
        p->setBrush( Qt::transparent );
        p->drawRect( m_area );
    }
    Component::paintSelected( p );
}
