//==============================================
//  copyright            : (C) 2003-2005 by Will Stokes
//==============================================
//  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.
//==============================================

//Systemwide includes
#include <qlayout.h>
#include <qlabel.h>
#include <qfont.h>
#include <qframe.h>
#include <qprogressbar.h>
#include <qfile.h>
#include <qdom.h>
#include <qstringlist.h>
#include <qtooltip.h>
#include <qpixmap.h>
#include <qdir.h>
#include <qmovie.h>
#include <qtimer.h>
#include <qsizegrip.h>

//Projectwide includes
#include "clickableLabel.h"
#include "statusWidget.h"
#include "titleWidget.h"
#include "window.h"
#include "../config.h"
#include "../configuration/configuration.h"

//==============================================
StatusWidget::StatusWidget(QWidget *parent,
                         const char* name ) : QWidget(parent,name)
{
 //create status message
  message = new QLabel( this );
  message->setText( "" );
  
  //create timer object and setup signals
  timer = new QTimer();
  connect(timer, SIGNAL(timeout()), this, SLOT(removeStatus()) );

  //create progress message and bar
  progressBar = new QProgressBar( this );
  progressBar->setCenterIndicator(true);
  progressBar->hide();
  curStep = 0;

  //-----------------------------------------------------------------
  //setup http object to check for updates, only check for updates if they are enabled
  updateAvailable = NULL;
  http.setHost( "albumshaper.sourceforge.net" );
  connect( &http, SIGNAL(done(bool)), this, SLOT(fileFetched(bool)) );
  if(((Window*)parentWidget())->getConfig()->getBool( "alerts", "showSoftwareUpdateAlerts"))
  {
    checkForUpdates();
  }
  //-----------------------------------------------------------------
  //place progress frame and status message in main grid
  grid = new QGridLayout( this, 1, 6, 0 );
  grid->setSpacing(WIDGET_SPACING);
  grid->setColSpacing( 0, WIDGET_SPACING );
  grid->addWidget( message, 0, 1, Qt::AlignVCenter );
  grid->addWidget( progressBar, 0, 2, Qt::AlignVCenter );
  grid->setColStretch( 3, 1 );

  //PLATFORM_SPECIFIC_CODE
  //mac os x puts in a size grip that can interfere with the updates icon, in order
  //to avoid this we manually place the size grip ourselves
  //windows users expect a grip too, but qt doesn't put one in by default. we'll add
  //it for them too. :-)
  #if defined(Q_OS_MACX) || defined(Q_OS_WIN)
  QSizeGrip* sizeGrip = new QSizeGrip( this );
  grid->addWidget( sizeGrip, 0, 5, Qt::AlignBottom );
  #endif

}
//==============================================
StatusWidget::~StatusWidget()
{
  delete timer;
  timer = NULL;
}
//==============================================
void StatusWidget::showProgressBar(QString message, int numSteps)
{
  //make sure timer is stopped so progress mess is never hidden
  //this can occur if a new event is begun before the previous events message is removed after default delay
  timer->stop();
  
  //setup progress bar and show it
  this->message->setText( message );
  progressBar->setProgress( 0, numSteps );
  progressBar->show();
  curStep = 0;
}
//==============================================
void StatusWidget::updateProgress(int progress, QString newMessage)
{
  curStep = progress;
  progressBar->setProgress( progress );

  //update message if provided
  if(newMessage != QString::null)
  {
    this->message->setText( newMessage );
  }
}
//==============================================
int StatusWidget::currentProgress()
{
  return curStep;
}
//==============================================
void StatusWidget::incrementProgress()
{
  curStep++;
  progressBar->setProgress( curStep );
}
//==============================================
void StatusWidget::setStatus( QString message )
{
  timer->stop();

  //hide progress bar
  progressBar->hide();

  //update status message
  this->message->setText( message );

  timer->start( 2000, TRUE );
}
//==============================================
void StatusWidget::removeStatus()
{
  //set status message to empty string
  message->setText( "" );
}
//==============================================
void StatusWidget::fileFetched(bool error)
{
  //------------------------------------------------------------
  //if unable to get file bail
  if(error)
  {
    return;
  }
  //------------------------------------------------------------
  //write releases to temp file
  QFile fetchedDoc( TEMP_DIR + QString("/releases.xml") );
  if(fetchedDoc.open(IO_WriteOnly))
  {
    //----------------------------
    //write to file
    QTextStream stream( &fetchedDoc );
    stream.setEncoding( QTextStream::UnicodeUTF8 );
    stream << QString( http.readAll() );
    fetchedDoc.close();
    //----------------------------
    //parse xml file, construct string list of releases
    //open file, bail if unable to
    if( !fetchedDoc.open( IO_ReadOnly ) )
    {
      return;
    }

    //parse dom
    QDomDocument xmlDom;
    if( !xmlDom.setContent( &fetchedDoc ) )
    {
      fetchedDoc.close();
      return;
    }

    //close file
    fetchedDoc.close();

    //construct stringlist of releases
    //actually, only get the first release since we don't need the others to determine if we
    //are out of date

    QStringList releases;
    QDomElement root = xmlDom.documentElement();
    QDomNode node = root.firstChild();
    QDomText val;
    bool thisVersionFound = false;
    while( !node.isNull() )
    {
      if( node.isElement() && node.nodeName() == "release" )
      {
        val = node.firstChild().toText();
        if(!val.isNull())
        {
          //append release #
          releases.append( QString(val.nodeValue()) );

          //is release this version?
          if( QString(val.nodeValue()).compare( QString(ALBUMSHAPER_VERSION) ) == 0 )
            thisVersionFound = true;
        }
      }
      node = node.nextSibling();
    }

    //compare first release to this release, if strings not equal then we're outdated,
    //update album shaper icon and start grabbing changelogs
    if(thisVersionFound && releases.first().compare( QString(ALBUMSHAPER_VERSION) ) != 0)
    {
      ClickableLabel* uA = new ClickableLabel( this );
      uA->setMovie( QMovie( QString(IMAGE_PATH)+"miscImages/updateAvailable.mng") );
      QToolTip::add( uA, tr("Your copy of Album Shaper is not up to date! Click here for details") );
      grid->addWidget( uA, 0, 4, Qt::AlignVCenter );
      connect( uA, SIGNAL(clicked()),
                    ((Window*)parentWidget())->getTitle(), SLOT(aboutProgram()) );
      uA->show();\
      updateAvailable = uA;
    }
  }
  //------------------------------------------------------------
}
//==============================================
void StatusWidget::checkForUpdates()
{
  if(updateAvailable != NULL)
    return;

  //attempt to get releases list from website. this lets us find out if this
  //copy of Album Shaper is outdated
  http.get( "/webService/releases.xml");
}
//==============================================
void StatusWidget::removeUpdatesIcon()
{
  delete updateAvailable;
  updateAvailable = NULL;
}
//==============================================
void StatusWidget::grabInput()
{
  grabKeyboard();
  grabMouse(); 
}
//==============================================
void StatusWidget::releaseInput()
{
  releaseKeyboard();
  releaseMouse();
}
//==============================================
