/*
**************************************************************************
                                 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 "pmfog.h"
#include "pmoutputdevice.h"
#include "pmxmlhelper.h"
#include "pmmemento.h"
#include "pmfogedit.h"
#include "pmvector.h"

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

bool PMFog::s_linkPossibilitiesCreated = false;
QValueList<PMDeclare::PMDeclareType> PMFog::s_linkPossibilities;

const int fogTypeDefault = 1;
const double distanceDefault = 0.0;
const PMColor colorDefault = PMColor( 0.0, 0.0, 0.0 );
const double lambdaDefault = 2.0;
const double fogOffsetDefault = 0.0;
const double fogAltDefault = 0.0;
const PMVector turbulenceDefault = PMVector( 0.0, 0.0, 0.0 );
const int octavesDefault = 6;
const double omegaDefault = 0.5;
const double turbDepthDefault = 0.5;
const PMVector upDefault = PMVector( 0.0, 1.0, 0.0 );

PMFog::PMFog( )
      : Base( )
{
   m_fogType = fogTypeDefault;
   m_distance = distanceDefault;
   m_color = colorDefault;
   m_enableTurbulence = false;
   m_valueVector = turbulenceDefault;
   m_octaves = octavesDefault;
   m_omega = omegaDefault;
   m_depth = turbDepthDefault;
   m_fogOffset = fogOffsetDefault;
   m_fogAlt = fogAltDefault;
   m_up = upDefault;
   m_lambda = 0;
}

PMFog::~PMFog( )
{
}

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

QString PMFog::description( ) const
{
   return i18n( "fog" );
}

bool PMFog::canInsert( PMObjectType t, const PMObject*,
                           const PMObjectList* ) const
{
   switch( t )
   {
      case PMTTranslate:
      case PMTScale:
      case PMTRotate:
      case PMTMatrix:
      case PMTComment:
      case PMTRaw:
         return true;
      default:
         break;
   }
   return false;
}

void PMFog::serialize( PMOutputDevice& dev ) const
{
   QString str;

   dev.objectBegin( "fog" );

   // Serialize the name of this object
   serializeName( dev );
   
   // Serialize a possible link
   if( linkedObject( ) )
   {
      if( linkedObject( )->firstChild( ) )
         dev.writeLine( linkedObject( )->id( ) );
      else
      {
         QString text;
         text = name( );
         if( text.isEmpty( ) )
            text = description( );

         dev.writeComment( QString( "No prototype for %1" ).arg( text ) );
      }
   }

   str.setNum( m_fogType );
   dev.writeLine( "fog_type " + str );

   str.setNum( m_distance );
   dev.writeLine( "distance " + str );
   dev.writeLine( " " + m_color.serialize( ) + " " );
   if( m_enableTurbulence )
   {
      dev.writeLine( "turbulence " + m_valueVector.serialize( ) );
      if( m_octaves != octavesDefault )
      {
         str.setNum(m_octaves);
         dev.writeLine( "octaves " + str );
      }
      if( m_omega != omegaDefault )
      {
         str.setNum(m_omega);
         dev.writeLine( "omega " + str );
      }
      if( m_lambda != lambdaDefault )
      {
         str.setNum(m_lambda);
         dev.writeLine( "lambda " + str );
      }
      if( m_depth != turbDepthDefault )
      {
         str.setNum(m_depth);
         dev.writeLine( "turb_depth " + str );
      }
   }
   if( m_fogType == 2 )
   {
      // Serialize ground fog variables
      str.setNum( m_fogOffset );
      dev.writeLine( "fog_offset " + str );
      str.setNum( m_fogAlt );
      dev.writeLine( "fog_alt " + str );
      dev.writeLine( "up " + m_up.serialize( ) );
   }
   // Serialize the children of this object
   PMNamedObject::serialize( dev );
   dev.objectEnd( );
}

void PMFog::serialize( QDomElement& e, QDomDocument& doc ) const
{
   Base::serialize( e, doc );
   e.setAttribute( "fog_type", m_fogType );
   e.setAttribute( "distance", m_distance );
   e.setAttribute( "color", m_color.serializeXML( ) );
   e.setAttribute( "enable_turbulence", m_enableTurbulence );
   e.setAttribute( "value_vector", m_valueVector.serializeXML( ) );
   e.setAttribute( "octaves", m_octaves );
   e.setAttribute( "omega", m_omega );
   e.setAttribute( "lambda", m_lambda );
   e.setAttribute( "depth", m_depth );
   e.setAttribute( "fog_offset", m_fogOffset );
   e.setAttribute( "fog_alt", m_fogAlt );
   e.setAttribute( "up", m_up.serializeXML( ) );
}
 
void PMFog::readAttributes( const PMXMLHelper& h )
{
   Base::readAttributes( h );
   m_fogType = h.intAttribute( "fog_type", fogTypeDefault );
   m_distance = h.doubleAttribute( "distance", distanceDefault );
   m_color = h.colorAttribute( "color", colorDefault );
   m_enableTurbulence = h.boolAttribute( "enable_turbulence", false );
   m_valueVector = h.vectorAttribute( "value_vector", turbulenceDefault );
   m_octaves = h.intAttribute( "octaves", octavesDefault );
   m_omega = h.doubleAttribute( "omega", omegaDefault );
   m_lambda = h.doubleAttribute( "lambda", lambdaDefault );
   m_depth = h.doubleAttribute( "depth", turbDepthDefault );
   m_fogOffset = h.doubleAttribute( "fog_offset", fogOffsetDefault );
   m_fogAlt = h.doubleAttribute( "fog_alt", fogAltDefault );
   m_up = h.vectorAttribute( "up", upDefault );
}

QValueList<PMDeclare::PMDeclareType> PMFog::linkPossibilities( ) const
{
   if( !s_linkPossibilitiesCreated )
   {
      s_linkPossibilities.append( PMDeclare::FogDeclare );
      s_linkPossibilitiesCreated = true;
   }
   return s_linkPossibilities;
}

void PMFog::setFogType( int c )
{
   if( c != m_fogType )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTFog, PMFogTypeID, m_fogType );
      m_fogType = c;
   }
}

void PMFog::setDistance( double c )
{
   if( c != m_distance )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTFog, PMDistanceID, m_distance );
      m_distance = c;
   }
}
 
void PMFog::setColor( const PMColor& c )
{
   if( c != m_color )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTFog, PMColorID, m_color );
      m_color = c;
   }
}
 
void PMFog::enableTurbulence( bool c )
{
   if( c != m_enableTurbulence )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTFog, PMEnableTurbulenceID, m_enableTurbulence );
      m_enableTurbulence = c;
   }
}

void PMFog::setValueVector( const PMVector& c )
{
   if( c != m_valueVector )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTFog, PMValueVectorID, m_valueVector );
      m_valueVector = c;
   }
}
 
void PMFog::setOctaves( int c )
{
   if( c != m_octaves )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTFog, PMOctavesID, m_octaves );
      m_octaves = c;
   }
}
 
void PMFog::setOmega( double c )
{
   if( c != m_omega )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTFog, PMOmegaID, m_omega );
      m_omega = c;
   }
}
 
void PMFog::setLambda( double c )
{
   if( c != m_lambda )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTFog, PMLambdaID, m_lambda );
      m_lambda = c;
   }
}
 
void PMFog::setDepth( double c )
{
   if( c != m_depth )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTFog, PMDepthID, m_depth );
      m_depth = c;
   }
}

void PMFog::setFogOffset( double c )
{
   if( c != m_fogOffset )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTFog, PMFogOffsetID, m_fogOffset );
      m_fogOffset = c;
   }
}

void PMFog::setFogAlt( double c )
{
   if( c != m_fogAlt )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTFog, PMFogAltID, m_fogAlt );
      m_fogAlt = c;
   }
}

void PMFog::setUp( const PMVector& c )
{
   if( c != m_up )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTFog, PMUpID, m_up );
      m_up = c;
   }
}
 
PMDialogEditBase* PMFog::editWidget( QWidget* parent ) const
{
   return new PMFogEdit( parent );
}

void PMFog::restoreMemento( PMMemento* s )
{
   PMMementoDataIterator it( s );
   PMMementoData* data;
 
   for( ; it.current( ); ++it )
   {
      data = it.current( );
      if( data->objectType( ) == PMTFog )
      {
         switch( data->valueID( ) )
         {
            case PMFogTypeID:
               setFogType( data->intData( ) );
               break;
            case PMDistanceID:
               setDistance( data->doubleData( ) );
               break;
            case PMColorID:
               setColor( data->colorData( ) );
               break;
            case PMEnableTurbulenceID:
               enableTurbulence( data->boolData( ) );
               break;
           case PMValueVectorID:
               setValueVector( data->vectorData( ) );
               break;
           case PMOctavesID:
               setOctaves( data->intData( ) );
               break;
            case PMOmegaID:
               setOmega( data->doubleData( ) );
               break;
            case PMLambdaID:
               setLambda( data->doubleData( ) );
               break;
            case PMDepthID:
               setDepth( data->doubleData( ) );
               break;
            case PMFogOffsetID:
               setFogOffset( data->doubleData( ) );
               break;
            case PMFogAltID:
               setFogAlt( data->doubleData( ) );
               break;
            case PMUpID:
               setUp( data->vectorData( ) );
               break;
            default:
               kdError( PMArea ) << "Wrong ID in PMFog::restoreMemento\n";
               break;
         }
      }
   }
   Base::restoreMemento( s );
}
