/*
**************************************************************************
                                 description
                             --------------------
    copyright            : (C) 2002 by Luis Carvalho
    email                : lpassos@mail.telepac.pt
**************************************************************************

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


#include "pmglobalsettings.h"
#include "pmoutputdevice.h"
#include "pmxmlhelper.h"
#include "pmmemento.h"
#include "pmglobalsettingsedit.h"

#include <kdebug.h>
#include "pmglobals.h"
#include <klocale.h>

const double adcBailoutDefault = 1.0 / 255.0;
const PMColor ambientLightDefault = PMColor( 1.0, 1.0, 1.0, 0.0, 0.0 );
const double assumedGammaDefault = 0.0;
const bool hfGray16Default = false;
const PMColor iridWaveLengthDefault = PMColor( 0.25, 0.18, 0.14, 0.0, 0.0 );
const int maxIntersectionsDefault = 0; // ???
const int maxTraceLevelDefault = 0;   // ???
const int numberWavesDefault = 10;
const bool radiosityDefault = false;
const double brightnessDefault = 1.0;
const int countDefault = 35; 
const double distanceMaximumDefault = 0; // ???
const double errorBoundDefault = 1.8; 
const double grayThresholdDefault = 0.0; 
const double lowErrorFactorDefault = 0.5; 
const double minimumReuseDefault = 0.015; 
const int nearestCountDefault = 5; 
const int recursionLimitDefault = 2;

PMGlobalSettings::PMGlobalSettings( )
      : Base( )
{
  m_adcBailout = adcBailoutDefault;
  m_ambientLight = ambientLightDefault;
  m_assumedGamma = assumedGammaDefault;
  m_hfGray16 = hfGray16Default;
  m_iridWaveLength = iridWaveLengthDefault;
  m_maxIntersections = maxIntersectionsDefault;
  m_maxTraceLevel = maxTraceLevelDefault;
  m_numberWaves = numberWavesDefault;
  m_radiosityEnabled = radiosityDefault;
  m_brightness = brightnessDefault;
  m_count = countDefault;
  m_distanceMaximum = distanceMaximumDefault;
  m_errorBound = errorBoundDefault;
  m_grayThreshold = grayThresholdDefault;
  m_lowErrorFactor = lowErrorFactorDefault;
  m_minimumReuse = minimumReuseDefault;
  m_nearestCount = nearestCountDefault;
  m_recursionLimit = recursionLimitDefault;
}

PMGlobalSettings::~PMGlobalSettings( )
{
}

bool PMGlobalSettings::isA( PMObjectType t ) const
{
   if( t == PMTGlobalSettings )
      return true;
   return Base::isA( t );
}

QString PMGlobalSettings::description( ) const
{
   return i18n( "global settings" );
}

void PMGlobalSettings::serialize( PMOutputDevice& dev ) const
{
   QString str1;

   dev.objectBegin( "global_settings" );

   if( m_adcBailout != adcBailoutDefault ) 
   {
      str1.setNum( m_adcBailout );
      dev.writeLine( "adc_bailout " + str1 );
   }
   if( m_ambientLight != ambientLightDefault )
      dev.writeLine( "ambient_light " + m_ambientLight.serialize( ) ); 
   if( m_assumedGamma != assumedGammaDefault )
   {
      str1.setNum( m_assumedGamma );
      dev.writeLine( "assumed_gamma " + str1 );
   }
   if( m_hfGray16 != hfGray16Default )
   {
      if( m_hfGray16 )
         dev.writeLine( "hf_gray_16 on" );
      else
         dev.writeLine( "hf_gray_16 off" );
   }
   if( m_iridWaveLength != iridWaveLengthDefault )
      dev.writeLine( "irid_wavelength " + m_iridWaveLength.serialize( ) );
   if( m_maxTraceLevel != maxTraceLevelDefault )
   {
      str1.setNum( m_maxTraceLevel );
      dev.writeLine( "max_trace_level " + str1 );
   } 
   if( m_maxIntersections != maxIntersectionsDefault )
   {
      str1.setNum( m_maxIntersections );
      dev.writeLine( "max_intersections " + str1 );
   }
   if( m_numberWaves != numberWavesDefault )
   {
      str1.setNum( m_numberWaves );
      dev.writeLine( "number_of_waves " + str1 );
   }
   if( m_radiosityEnabled )
   {
      dev.objectBegin( "radiosity" );
      if( m_brightness != brightnessDefault )
      {
         str1.setNum( m_brightness );
         dev.writeLine( "brightness " + str1 );
      }
      if( m_count != countDefault )
      {
         str1.setNum( m_count );
         dev.writeLine( "count " + str1 );
      }
      if( m_distanceMaximum != distanceMaximumDefault )
      {
         str1.setNum( m_distanceMaximum );
         dev.writeLine( "distance_maximum " + str1 );
      }
      if( m_errorBound != errorBoundDefault )
      {
         str1.setNum( m_errorBound );
         dev.writeLine( "error_bound " + str1 );
      }
      if( m_grayThreshold != grayThresholdDefault )
      {
         str1.setNum( m_grayThreshold );
         dev.writeLine( "gray_threshold " + str1 );
      }
      if( m_lowErrorFactor != lowErrorFactorDefault )
      {
         str1.setNum( m_lowErrorFactor );
         dev.writeLine( "low_error_factor " + str1 );
      }
      if( m_minimumReuse != minimumReuseDefault )
      {
         str1.setNum( m_minimumReuse );
         dev.writeLine( "minimum_reuse " + str1 );
      }
      if( m_nearestCount != nearestCountDefault )
      {
         str1.setNum( m_nearestCount );
         dev.writeLine( "nearest_count " + str1 );
      }
      if( m_recursionLimit != recursionLimitDefault )
      {
         str1.setNum( m_recursionLimit );
         dev.writeLine( "recursion_limit " + str1 );
      }
      dev.objectEnd( );
   }
   dev.objectEnd( );
}

void PMGlobalSettings::serialize( QDomElement& e, QDomDocument& ) const
{
   e.setAttribute( "adc_bailout", m_adcBailout );
   e.setAttribute( "ambient_light", m_ambientLight.serializeXML( ) );
   e.setAttribute( "assumed_gamma", m_assumedGamma );
   e.setAttribute( "hf_gray_16", m_hfGray16 );
   e.setAttribute( "irid_wavelength", m_iridWaveLength.serializeXML( ) );
   e.setAttribute( "max_intersections", m_maxIntersections );
   e.setAttribute( "max_trace_level", m_maxTraceLevel );
   e.setAttribute( "number_of_waves", m_numberWaves );
   e.setAttribute( "radiosity", m_radiosityEnabled );
   e.setAttribute( "brightness", m_brightness );
   e.setAttribute( "count", m_count );
   e.setAttribute( "distance_maximum", m_distanceMaximum );
   e.setAttribute( "error_bound", m_errorBound );
   e.setAttribute( "gray_threshold", m_grayThreshold );
   e.setAttribute( "low_error_factor", m_lowErrorFactor );
   e.setAttribute( "minimum_reuse", m_minimumReuse );
   e.setAttribute( "nearest_count", m_nearestCount );
   e.setAttribute( "recursion_limit", m_recursionLimit );
}
 
void PMGlobalSettings::readAttributes( const PMXMLHelper& h )
{
   m_adcBailout = h.doubleAttribute( "adc_bailout", adcBailoutDefault );
   m_ambientLight = h.colorAttribute( "ambient_light", ambientLightDefault );
   m_assumedGamma = h.doubleAttribute( "assumed_gamma", assumedGammaDefault );
   m_hfGray16 = h.boolAttribute( "hf_gray_16", hfGray16Default );
   m_iridWaveLength = h.colorAttribute( "irid_wavelength", iridWaveLengthDefault );
   m_maxIntersections = h.intAttribute( "max_intersections", maxIntersectionsDefault );
   m_maxTraceLevel = h.intAttribute( "max_trace_level", maxTraceLevelDefault );
   m_numberWaves = h.intAttribute( "number_of_waves", numberWavesDefault );
   m_radiosityEnabled = h.boolAttribute( "radiosity", radiosityDefault );
   m_brightness = h.doubleAttribute( "brightness", brightnessDefault );
   m_count = h.intAttribute( "count", countDefault );
   m_distanceMaximum = h.doubleAttribute( "distance_maximum", distanceMaximumDefault );
   m_errorBound = h.doubleAttribute( "error_bound", errorBoundDefault );
   m_grayThreshold = h.doubleAttribute( "gray_threshold", grayThresholdDefault );
   m_lowErrorFactor = h.doubleAttribute( "low_error_factor", lowErrorFactorDefault );
   m_minimumReuse = h.doubleAttribute( "minimum_reuse", minimumReuseDefault );
   m_nearestCount = h.intAttribute( "nearest_count", nearestCountDefault );
   m_recursionLimit = h.intAttribute( "recursion_limit", recursionLimitDefault );
}

void PMGlobalSettings::setAdcBailout( double c )
{
   if( c != m_adcBailout )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTGlobalSettings, PMAdcBailoutID, m_adcBailout );
      m_adcBailout = c;
   }
}
 
void PMGlobalSettings::setAmbientLight( const PMColor& c )
{
   if( c != m_ambientLight )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTGlobalSettings, PMAmbientLightID, m_ambientLight );
      m_ambientLight = c;
   }
}
 
void PMGlobalSettings::setAssumedGamma( double c )
{
   if( c != m_assumedGamma )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTGlobalSettings, PMAssumedGammaID, m_assumedGamma );
      m_assumedGamma = c;
   }
}

void PMGlobalSettings::setIridWaveLength( const PMColor& c )
{
   if( c != m_iridWaveLength )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTGlobalSettings, PMIridWaveLengthID, m_iridWaveLength );
      m_iridWaveLength = c;
   }
}

void PMGlobalSettings::setHfGray16( bool c )
{
   if( c != m_hfGray16 )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTGlobalSettings, PMHfGray16ID, m_hfGray16 );
      m_hfGray16 = c;
   }
}
 
void PMGlobalSettings::setMaxIntersections( int c )
{
   if( c != m_maxIntersections )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTGlobalSettings, PMMaxIntersectionsID, m_maxIntersections );
      m_maxIntersections = c;
   }
}
 
void PMGlobalSettings::setMaxTraceLevel( int c )
{
   if( c != m_maxTraceLevel )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTGlobalSettings, PMMaxTraceLevelID, m_maxTraceLevel );
      m_maxTraceLevel = c;
   }
}

void PMGlobalSettings::setNumberWaves( int c )
{
   if( c != m_numberWaves )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTGlobalSettings, PMNumberWavesID, m_numberWaves );
      m_numberWaves = c;
   }
}
 
void PMGlobalSettings::enableRadiosity( bool c )
{
   if( c != m_radiosityEnabled )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTGlobalSettings, PMRadiosityEnabledID, m_radiosityEnabled );
      m_radiosityEnabled = c;
   }
}

void PMGlobalSettings::setBrightness( double c )
{
   if( c != m_brightness )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTGlobalSettings, PMBrightnessID, m_brightness );
      m_brightness = c;
   }
}
 
void PMGlobalSettings::setCount( int c )
{
   if( c != m_count )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTGlobalSettings, PMCountID, m_count );
      m_count = c;
   }
}

void PMGlobalSettings::setDistanceMaximum( double c )
{
   if( c != m_distanceMaximum )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTGlobalSettings, PMDistanceMaximumID, m_distanceMaximum );
      m_distanceMaximum = c;
   }
}

void PMGlobalSettings::setErrorBound( double c )
{
   if( c != m_errorBound )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTGlobalSettings, PMErrorBoundID, m_errorBound );
      m_errorBound = c;
   }
}

void PMGlobalSettings::setGrayThreshold( double c )
{
   if( c != m_grayThreshold )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTGlobalSettings, PMGrayThresholdID, m_grayThreshold );
      m_grayThreshold = c;
   }
}

void PMGlobalSettings::setLowErrorFactor( double c )
{
   if( c != m_lowErrorFactor )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTGlobalSettings, PMLowErrorFactorID, m_lowErrorFactor );
      m_lowErrorFactor = c;
   }
}

void PMGlobalSettings::setMinimumReuse( double c )
{
   if( c != m_minimumReuse )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTGlobalSettings, PMMinimumReuseID, m_minimumReuse );
      m_minimumReuse = c;
   }
}

void PMGlobalSettings::setNearestCount( int c )
{
   if( c != m_nearestCount )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTGlobalSettings, PMNearestCountID, m_nearestCount );
      m_nearestCount = c;
   }
}

void PMGlobalSettings::setRecursionLimit( int c )
{
   if( c != m_recursionLimit )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTGlobalSettings, PMRecursionLimitID, m_recursionLimit );
      m_recursionLimit = c;
   }
}

PMDialogEditBase* PMGlobalSettings::editWidget( QWidget* parent ) const
{
   return new PMGlobalSettingsEdit( parent );
}

void PMGlobalSettings::restoreMemento( PMMemento* s )
{
   PMMementoDataIterator it( s );
   PMMementoData* data;
 
   for( ; it.current( ); ++it )
   {
      data = it.current( );
      if( data->objectType( ) == PMTGlobalSettings )
      {
         switch( data->valueID( ) )
         {
            case PMAdcBailoutID:
               setAdcBailout( data->doubleData( ) );
               break;
            case PMAmbientLightID:
               setAmbientLight( data->colorData( ) );
               break;
            case PMAssumedGammaID:
               setAssumedGamma( data->doubleData( ) );
               break;
            case PMHfGray16ID:
               setHfGray16( data->boolData( ) );
               break;
            case PMIridWaveLengthID:
               setIridWaveLength( data->colorData( ) );
               break;
           case PMMaxIntersectionsID:
               setMaxIntersections( data->intData( ) );
               break;
            case PMMaxTraceLevelID:
               setMaxTraceLevel( data->intData( ) );
               break;
            case PMNumberWavesID:
               setNumberWaves( data->intData( ) );
               break;
            case PMRadiosityEnabledID:
               enableRadiosity( data->boolData( ) );
               break;
            case PMBrightnessID:
               setBrightness( data->doubleData( ) );
               break;
            case PMCountID:
               setCount( data->intData( ) );
               break;
            case PMDistanceMaximumID:
               setDistanceMaximum( data->doubleData( ) );
               break;
            case PMErrorBoundID:
               setErrorBound( data->doubleData( ) );
               break;
            case PMGrayThresholdID:
               setGrayThreshold( data->doubleData( ) );
               break;
            case PMLowErrorFactorID:
               setLowErrorFactor( data->doubleData( ) );
               break;
            case PMMinimumReuseID:
               setMinimumReuse( data->doubleData( ) );
               break;
            case PMNearestCountID:
               setNearestCount( data->intData( ) );
               break;
            case PMRecursionLimitID:
               setRecursionLimit( data->intData( ) );
               break;
            default:
               kdError( PMArea ) << "Wrong ID in PMGlobalSettings::restoreMemento\n";
               break;
         }
      }
   }
   Base::restoreMemento( s );
}
