//==============================================
//  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 <qstring.h>
#include <qimage.h>
#include <qapplication.h>
#include <qdir.h>
#include <qprocess.h>
#include <qfile.h>
#include <qdir.h>

//PLATFORM_SPECIFIC_CODE
#if defined(Q_OS_WIN)
#include <windows.h>
#endif //Q_OS_WIN

//Projectwide includes
#include "wallpaperTools.h"
#include "fileTools.h"
#include "../album.h"
#include "../photo.h"
#include "../../gui/window.h"
#include "../../gui/titleWidget.h"

//==============================================
void setWallpaper( Photo* phto )
{
  //Get full size image dimensions
  int imageW, imageH;
  getImageSize( phto->getImageFilename(), imageW, imageH );

  //If image is larger than either screen dimension then scale it down
  int screenW = qApp->desktop()->screenGeometry().size().width();
  int screenH = qApp->desktop()->screenGeometry().size().height();

  //If image is larger than either screen dimensions then scale it to fit
  QImage scaledImage;
  if( imageW > screenW || imageH > screenH )
  {
    scaleImage( phto->getImageFilename(), scaledImage, screenW, screenH );
    imageW = scaledImage.width();
    imageH = scaledImage.height();
  }

  //If image is <75% of either screen dimensions, center it when setting it to the background
  //PLATFORM_SPECIFIC_CODE
  #ifndef Q_OS_MACX
  const bool centerImage = (imageW < 0.75*screenW) || (imageH < 0.75*screenH);
  #endif

  //Determine the final output filename. On Windows this is pretty simple, but on OSX and KDE/Unix
  //I've found that repeatedly setting the same filename to be used as the background does not result in a 
  //refreshing of the background image. Apparently these window managers are trying to be "smart" and 
  //avoid refreshing when the image has not changed, but in our case we are changing the image content,
  //just not the image filename. Alas a simple fix to this problem is to alternate using spaces and 
  //underscores in the image filename and removing the old image. Another option might be to first set the 
  //background image to null, but this might result in unwanted flicker so we use the slightly more 
  //complicated approach involving alternating filenames.

  //PLATFORM_SPECIFIC_CODE

  //Windows
  #if defined(Q_OS_WIN)

  //determine location to store the desktop image
  QString outFilename;
  if( !getWindowsFolderLocation(LOCAL_SETTINGS_APPLICATION_DATA,  outFilename) )
  {
    outFilename = getenv("USERPROFILE") + QString("/Local Settings/Application Data");
  }
  outFilename = QDir::convertSeparators( outFilename + "/Album Shaper/Album Shaper Wallpaper.bmp" );
  
  //windows only support setting background image using BMP format, so if image was not scaled
  //load it so we can use QImage to save it as a BMP image now
  if( scaledImage.isNull() )  
  { scaledImage.load( phto->getImageFilename() ); }
  
  //save image out
  scaledImage.save( outFilename, "BMP" );
 
  //OSX and other forms of UNIX
  #else

  //determine location to store the desktop image
  #if defined(Q_OS_MACX)
  QString outFilename1 = QDir::homeDirPath() + QString("/Pictures/Album Shaper Wallpaper.jpg");
  QString outFilename2 = QDir::homeDirPath() + QString("/Pictures/Album_Shaper_Wallpaper.jpg");  
  #else
  QString outFilename1 = QDir::homeDirPath() + QString("/.albumShaper/Album Shaper Wallpaper.jpg");
  QString outFilename2 = QDir::homeDirPath() + QString("/.albumShaper/Album_Shaper_Wallpaper.jpg");
  #endif

  QString chosenFilename;
  QString oldFilename;
  
  //check if outFilename already exists. MacOSX is annoying in that when we create an apple event to 
  //set the desktop wallpaper the Finder appears to ignore the event if the filename is the same
  //the current filename. Ug, so to trick it use the opposite filename (swap spaces with _'s in filename)
  QDir tmpDir;
  if(tmpDir.exists( outFilename1 ) )
  {
    chosenFilename = outFilename2;
    oldFilename = outFilename1;
  }
  else if( tmpDir.exists( outFilename2 ) )
  {
    chosenFilename = outFilename1;
    oldFilename = outFilename2;
  }
  else
  {
    chosenFilename = outFilename1;
  }
  
  //save out file in JPG format
  if( !scaledImage.isNull() )
  {
    scaledImage.save( chosenFilename, "JPEG", 95 );
  }
  else
  {
    copyFile( phto->getImageFilename(), chosenFilename );
  }

  #endif    

  //-------------------------------
  // The output filename has been determined, and the image prepared.
  // Now save out the scaled image and set the wallpaper using system specific methods.
  //-------------------------------
  //PLATFORM_SPECIFIC_CODE

  //Windows
  #if defined(Q_OS_WIN)

  //Set tile and stretch values
  HKEY key;
  char data[8];
  if( RegOpenKeyExA( HKEY_CURRENT_USER, "Control Panel\\Desktop", 0, KEY_SET_VALUE, &key) == ERROR_SUCCESS)
  {
    //Set stretch factor, only stretch (2) if not using centering
    itoa( centerImage ? 0 : 2, data, 10);
    RegSetValueExA(key, "WallpaperStyle", NULL, REG_SZ, (UCHAR*)data, 8);

    //Never tile (0)
    itoa(0, data, 10);
    RegSetValueExA(key, "TileWallpaper", NULL, REG_SZ, (UCHAR*)data, 8);  

    //Close the key
    RegCloseKey(key);
  }
  
  //set background wallpaper
  SystemParametersInfoA( SPI_SETDESKWALLPAPER, 0,
                         (void*) outFilename.ascii(),
                         SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE );
  //-------------------------------
  //MacOSX
  #elif defined(Q_OS_MACX)

  //create script
  QString scriptFilename = ((Window*)qApp->mainWidget())->getTitle()->getAlbum()->getTmpDir() +
    "/tmpBackgroundScript";

  QFile file( scriptFilename );
  if(file.open(IO_WriteOnly))
  {
    //-----
    QTextStream stream;
    stream.setDevice( &file );
    stream.setEncoding( QTextStream::UnicodeUTF8 );
    //-----
    stream << "tell application \"Finder\"\n";
    stream << "set pFile to POSIX file \"" << chosenFilename.ascii() << "\"\n";
    stream << "set desktop picture to file pFile\n";
    stream << "end tell";
  }
  file.close();
  
  //run script to set background
  QProcess p;
  p.addArgument( "/usr/bin/osascript" );
  p.addArgument( scriptFilename );
  p.start();
  
  //if there is an old file remove it
  if(!oldFilename.isNull())    
  { tmpDir.remove( oldFilename ); }

  //-------------------------------
  //UNIX
  #else

  //first try setting KDE background through DCOP interface
  {
    QProcess p;   
    p.clearArguments();
    p.addArgument( "dcop" );
    p.addArgument( "kdesktop" );
    p.addArgument( "KBackgroundIface" );
    p.addArgument( "setWallpaper" );
    p.addArgument( chosenFilename.ascii() );

    //if the image width and height are at least 75% of the screen size then
    //use CENTERMAXSPECT. This will scale the image to fit the screen but 
    //will not warp it by changing it's effective aspect ratio. Otherwise scaling up 
    //will cause visible pixelation so user the CENTERED setting.
    const int CENTERED = 1;
    const int CENTER_MAXPECT = 4;
    int positionOption = centerImage ? CENTERED : CENTER_MAXPECT;
    p.addArgument( QString("%1").arg(positionOption) );

    //attempt to background now using DCOP interface
    p.start();
  }
  
  //try setting GNOME background using gconftool
  {
    QProcess p;   
    p.clearArguments();
    p.addArgument( "gconftool-2" );
    p.addArgument( "-t" );
    p.addArgument( "string" );
    p.addArgument( "-s" );
    p.addArgument( "/desktop/gnome/background/picture_filename" );
    p.addArgument( chosenFilename.ascii() );
    p.start();  
  }

  //try setting WindowMaker background using wmsetbg
  {
    QProcess p;   
    p.clearArguments();
    p.addArgument( "wmsetbg" );
    p.addArgument( "--maxscale" );
    p.addArgument( "-u" );
    p.addArgument( chosenFilename.ascii() );
    p.start();  
  }
  
  //if there is an old file remove it
  if(!oldFilename.isNull())    
  { tmpDir.remove( oldFilename ); }
  //-------------------------------
  #endif
}
//==============================================
bool setWallpaperSupported()
{
  //OSX supported!
  #if defined(Q_OS_MACX)
  return true;
  
  //Windows is supported!
  #elif defined(Q_OS_WIN)
  return true;

  //Last try, check if dcop or gconftool-2 can be used
  #else
  QProcess p;

  p.addArgument( "dcop" );
  bool DCOP_Present = p.start();

  p.clearArguments();
  p.addArgument( "gconftool-2" );
  bool gconftool_Present = p.start();

  p.clearArguments();
  p.addArgument( "wmsetbg" );
  bool wmsetbg_Present = p.start();

  return ( DCOP_Present || gconftool_Present || wmsetbg_Present );

  #endif
}
//==============================================

