/*
**************************************************************************
                                 description
                             --------------------
    copyright            : (C) 2001 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 "pmfinish.h"
#include "pmoutputdevice.h"
#include "pmxmlhelper.h"
#include "pmmemento.h"
#include "pmfinishedit.h"

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

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

const PMColor ambientColorDefault = PMColor( 0.0, 0.0, 0.0, 0.0, 0.0 );
const double diffuseDefault = 0.6;
const double brillianceDefault = 1.0;
const double crandDefault = 0.0;
const double phongDefault = 0.0;
const double phongSizeDefault = 40.0;
const double metallicDefault = 1.0;
const double specularDefault = 0.0;
const double roughnessDefault = 0.05; 
const PMColor reflectionColorDefault = PMColor( 0.0, 0.0, 0.0, 0.0, 0.0 );
const double reflectionExponentDefault = 1.0; 
const double iridAmountDefault = 0.0; 
const double iridThicknessDefault = 0.0; 
const double iridTurbulenceDefault = 0.0; 

PMFinish::PMFinish( )
      : Base( )
{
  m_ambientColor = ambientColorDefault;
  m_diffuse = diffuseDefault;
  m_brilliance = brillianceDefault;
  m_crand = crandDefault;
  m_phong = phongDefault;
  m_phongSize = phongSizeDefault;
  m_metallic = metallicDefault;
  m_specular = specularDefault;
  m_roughness = roughnessDefault;
  m_reflectionExponent = reflectionExponentDefault;
  m_reflectionColor = reflectionColorDefault;
  m_iridAmount = iridAmountDefault;
  m_iridThickness = iridThicknessDefault;
  m_iridTurbulence = iridTurbulenceDefault;
  m_enableAmbient = false;
  m_enableDiffuse = false;
  m_enableBrilliance = false;
  m_enableCrand = false;
  m_enablePhong = false;
  m_enablePhongSize = false;
  m_enableMetallic = false;
  m_enableSpecular = false;
  m_enableRoughness = false;
  m_enableReflection = false;
  m_enableExponent = false;
  m_irid = false;
}

PMFinish::~PMFinish( )
{
}

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

QString PMFinish::description( ) const
{
   return i18n( "finish" );
}


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

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

   dev.objectBegin( "finish" );

   Base::serialize( dev );

   if( m_enableAmbient ) 
      dev.writeLine( "ambient " + m_ambientColor.serialize( ) ); 
   if( m_enableDiffuse )
   {
      str1.setNum( m_diffuse );
      dev.writeLine( "diffuse " + str1 );
   }
   if( m_enableBrilliance )
   {
      str1.setNum( m_brilliance );
      dev.writeLine( "brilliance " + str1 );
   }
   if( m_enablePhong )
   {
      str1.setNum( m_phong );
      dev.writeLine( "phong " + str1 );
   }
   if( m_enablePhongSize )
   {
      str1.setNum( m_phongSize );
      dev.writeLine( "phong_size " + str1 );
   } 
   if( m_enableMetallic )
   {
      str1.setNum( m_metallic );
      dev.writeLine( "metallic " + str1 );
   }
   if( m_enableSpecular )
   {
      str1.setNum( m_specular );
      dev.writeLine( "specular " + str1 );
   }
   if( m_enableRoughness )
   {
      str1.setNum( m_roughness );
      dev.writeLine( "roughness " + str1 );
   }
   if( m_enableReflection )
   {
      dev.writeLine( "reflection " + m_reflectionColor.serialize( ) );
   }
   if( m_enableExponent )
   {
      str1.setNum( m_reflectionExponent );
      dev.writeLine( "reflection_exponent " + str1 );
   }
   if( m_irid )
   {
      str1.setNum( m_iridAmount );
      dev.writeLine( "irid { " + str1 );
      str1.setNum( m_iridThickness );
      dev.writeLine( "thickness " + str1 );
      str1.setNum( m_iridTurbulence );
      dev.writeLine( "turbulence " + str1 + " } " );
   }
   if( m_enableCrand )
   {
      str1.setNum( m_crand );
      dev.writeLine( "crand " + str1 );
   }
   dev.objectEnd( );
}

void PMFinish::serialize( QDomElement& e, QDomDocument& doc ) const
{
   Base::serialize( e, doc );
   e.setAttribute( "enable_ambient", m_enableAmbient );
   e.setAttribute( "enable_diffuse", m_enableDiffuse );
   e.setAttribute( "enable_brilliance", m_enableBrilliance );
   e.setAttribute( "enable_crand", m_enableCrand );
   e.setAttribute( "enable_phong", m_enablePhong );
   e.setAttribute( "enable_phong_size", m_enablePhongSize );
   e.setAttribute( "enable_metallic", m_enableMetallic );
   e.setAttribute( "enable_specular", m_enableSpecular );
   e.setAttribute( "enable_roughness", m_enableRoughness );
   e.setAttribute( "enable_reflection", m_enableReflection );
   e.setAttribute( "enable_exponent", m_enableExponent );
   e.setAttribute( "ambient", m_ambientColor.serializeXML( ) );
   e.setAttribute( "diffuse", m_diffuse );
   e.setAttribute( "brilliance", m_brilliance );
   e.setAttribute( "crand", m_crand );
   e.setAttribute( "phong", m_phong );
   e.setAttribute( "phongsize", m_phongSize );
   e.setAttribute( "metallic", m_metallic );
   e.setAttribute( "specular", m_specular );
   e.setAttribute( "roughness", m_roughness );
   e.setAttribute( "reflection", m_reflectionColor.serializeXML( ) );
   e.setAttribute( "reflection_exponent", m_reflectionExponent );
   e.setAttribute( "irid", m_irid );
   e.setAttribute( "irid_amount", m_iridAmount );
   e.setAttribute( "irid_thickness", m_iridThickness );
   e.setAttribute( "irid_turbulence", m_iridTurbulence );
}
 
void PMFinish::readAttributes( const PMXMLHelper& h )
{
   Base::readAttributes( h );
   m_enableAmbient = h.boolAttribute( "enable_ambient", false );
   m_enableDiffuse = h.boolAttribute( "enable_diffuse", false );
   m_enableBrilliance = h.boolAttribute( "enable_brilliance", false );
   m_enableCrand = h.boolAttribute( "enable_crand", false );
   m_enablePhong = h.boolAttribute( "enable_phong", false );
   m_enablePhongSize = h.boolAttribute( "enable_phong_size", false );
   m_enableMetallic = h.boolAttribute( "enable_metallic", false );
   m_enableSpecular = h.boolAttribute( "enable_specular", false );
   m_enableRoughness = h.boolAttribute( "enable_roughness", false );
   m_enableReflection = h.boolAttribute( "enable_reflection", false );
   m_enableExponent = h.boolAttribute( "enable_exponent", false );
   m_irid = h.boolAttribute( "irid", false );
   m_ambientColor = h.colorAttribute( "ambient", ambientColorDefault );
   m_diffuse = h.doubleAttribute( "diffuse", diffuseDefault );
   m_brilliance = h.doubleAttribute( "brilliance", crandDefault );
   m_crand = h.doubleAttribute( "crand", crandDefault );
   m_phong = h.doubleAttribute( "phong", phongDefault );
   m_phongSize = h.doubleAttribute( "phongsize", phongSizeDefault );
   m_metallic = h.doubleAttribute( "metallic", metallicDefault );
   m_specular = h.doubleAttribute( "specular", specularDefault );
   m_roughness = h.doubleAttribute( "roughness", roughnessDefault );
   m_reflectionColor = h.colorAttribute( "reflection", reflectionColorDefault );
   m_reflectionExponent = h.doubleAttribute( "reflectionExponent", reflectionExponentDefault );
   m_iridAmount = h.doubleAttribute( "irid_amount", iridAmountDefault );
   m_iridThickness = h.doubleAttribute( "irid_thickness", iridThicknessDefault );
   m_iridTurbulence = h.doubleAttribute( "irid_turbulence", iridTurbulenceDefault );
}

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

void PMFinish::setPhong( double c )
{
   if( c != m_phong )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTFinish, PMPhongID, m_phong );
      m_phong = c;
   }
}
 
void PMFinish::setPhongSize( double c )
{
   if( c != m_phongSize )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTFinish, PMPhongSizeID, m_phongSize );
      m_phongSize = c;
   }
}
 
void PMFinish::setMetallic( double c )
{
   if( c != m_metallic )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTFinish, PMMetallicID, m_metallic );
      m_metallic = c;
   }
}

void PMFinish::setAmbientColor( const PMColor& c )
{
   if( c != m_ambientColor )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTFinish, PMAmbientColorID, m_ambientColor );
      m_ambientColor = c;
   }
}

void PMFinish::setDiffuse( double c )
{
   if( c != m_diffuse )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTFinish, PMDiffuseID, m_diffuse );
      m_diffuse = c;
   }
}
 
void PMFinish::setBrilliance( double c )
{
   if( c != m_brilliance )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTFinish, PMBrillianceID, m_brilliance );
      m_brilliance = c;
   }
}
 
void PMFinish::setCrand( double c )
{
   if( c != m_crand )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTFinish, PMCrandID, m_crand );
      m_crand = c;
   }
}

void PMFinish::setSpecular( double c )
{
   if( c != m_specular )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTFinish, PMSpecularID, m_specular );
      m_specular = c;
   }
}
 
void PMFinish::setRoughness( double c )
{
   if( c != m_roughness )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTFinish, PMRoughnessID, m_roughness );
      m_roughness = c;
   }
}

void PMFinish::setReflectionColor( const PMColor& c )
{
   if( c != m_reflectionColor )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTFinish, PMReflectionColorID, m_reflectionColor );
      m_reflectionColor = c;
   }
}
 
void PMFinish::setReflectionExponent( double c )
{
   if( c != m_reflectionExponent )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTFinish, PMReflectionExponentID, m_reflectionExponent );
      m_reflectionExponent = c;
   }
}

void PMFinish::setIrid( bool c )
{
   if( c != m_irid )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTFinish, PMIridID, m_irid );
      m_irid = c;
   }
}

void PMFinish::enableAmbient( bool c )
{
   if( c != m_enableAmbient )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTFinish, PMEnableAmbientID, m_enableAmbient );
      m_enableAmbient = c;
   }
}

void PMFinish::enableDiffuse( bool c )
{
   if( c != m_enableDiffuse )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTFinish, PMEnableDiffuseID, m_enableDiffuse );
      m_enableDiffuse = c;
   }
}

void PMFinish::enablePhong( bool c )
{
   if( c != m_enablePhong )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTFinish, PMEnablePhongID, m_enablePhong );
      m_enablePhong = c;
   }
}

void PMFinish::enablePhongSize( bool c )
{
   if( c != m_enablePhongSize )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTFinish, PMEnablePhongSizeID, m_enablePhongSize );
      m_enablePhongSize = c;
   }
}

void PMFinish::enableBrilliance( bool c )
{
   if( c != m_enableBrilliance )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTFinish, PMEnableBrillianceID, m_enableBrilliance );
      m_enableBrilliance = c;
   }
}

void PMFinish::enableCrand( bool c )
{
   if( c != m_enableCrand )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTFinish, PMEnableCrandID, m_enableCrand );
      m_enableCrand = c;
   }
}

void PMFinish::enableSpecular( bool c )
{
   if( c != m_enableSpecular )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTFinish, PMEnableSpecularID, m_enableSpecular );
      m_enableSpecular = c;
   }
}

void PMFinish::enableRoughness( bool c )
{
   if( c != m_enableRoughness )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTFinish, PMEnableRoughnessID, m_enableRoughness );
      m_enableRoughness = c;
   }
}

void PMFinish::enableMetallic( bool c )
{
   if( c != m_enableMetallic )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTFinish, PMEnableMetallicID, m_enableMetallic );
      m_enableMetallic = c;
   }
}

void PMFinish::enableReflection( bool c )
{
   if( c != m_enableReflection )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTFinish, PMEnableReflectionID, m_enableReflection );
      m_enableReflection = c;
   }
}

void PMFinish::enableExponent( bool c )
{
   if( c != m_enableExponent )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTFinish, PMEnableExponentID, m_enableExponent );
      m_enableExponent = c;
   }
}

void PMFinish::setIridAmount( double c )
{
   if( c != m_iridAmount )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTFinish, PMIridAmountID, m_iridAmount );
      m_iridAmount = c;
   }
}

void PMFinish::setIridThickness( double c )
{
   if( c != m_iridThickness )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTFinish, PMIridThicknessID, m_iridThickness );
      m_iridThickness = c;
   }
}

void PMFinish::setIridTurbulence( double c )
{
   if( c != m_iridTurbulence )
   {
      if( m_pMemento )
         m_pMemento->addData( PMTFinish, PMIridTurbulenceID, m_iridTurbulence );
      m_iridTurbulence = c;
   }
}

PMDialogEditBase* PMFinish::editWidget( QWidget* parent ) const
{
   return new PMFinishEdit( parent );
}

void PMFinish::restoreMemento( PMMemento* s )
{
   PMMementoDataIterator it( s );
   PMMementoData* data;
 
   for( ; it.current( ); ++it )
   {
      data = it.current( );
      if( data->objectType( ) == PMTFinish )
      {
         switch( data->valueID( ) )
         {
            case PMAmbientColorID:
               setAmbientColor( data->colorData( ) );
               break;
            case PMDiffuseID:
               setDiffuse( data->doubleData( ) );
               break;
            case PMBrillianceID:
               setBrilliance( data->doubleData( ) );
               break;
            case PMCrandID:
               setCrand( data->doubleData( ) );
               break;
           case PMPhongID:
               setPhong( data->doubleData( ) );
               break;
            case PMPhongSizeID:
               setPhongSize( data->doubleData( ) );
               break;
            case PMMetallicID:
               setMetallic( data->doubleData( ) );
               break;
            case PMSpecularID:
               setSpecular( data->doubleData( ) );
               break;
            case PMRoughnessID:
               setRoughness( data->doubleData( ) );
               break;
            case PMReflectionColorID:
               setReflectionColor( data->colorData( ) );
               break;
            case PMReflectionExponentID:
               setReflectionExponent( data->doubleData( ) );
               break;
            case PMIridID:
               setIrid( data->boolData( ) );
               break;
            case PMIridAmountID:
               setIridAmount( data->doubleData( ) );
               break;
            case PMIridThicknessID:
               setIridThickness( data->doubleData( ) );
               break;
            case PMIridTurbulenceID:
               setIridTurbulence( data->doubleData( ) );
               break;
            case PMEnableAmbientID:
               enableAmbient( data->boolData( ) );
               break;
            case PMEnablePhongID:
               enablePhong( data->boolData( ) );
               break;
            case PMEnablePhongSizeID:
               enablePhongSize( data->boolData( ) );
               break;
            case PMEnableDiffuseID:
               enableDiffuse( data->boolData( ) );
               break;
            case PMEnableBrillianceID:
               enableBrilliance( data->boolData( ) );
               break;
            case PMEnableCrandID:
               enableCrand( data->boolData( ) );
               break;
            case PMEnableSpecularID:
               enableSpecular( data->boolData( ) );
               break;
            case PMEnableRoughnessID:
               enableRoughness( data->boolData( ) );
               break;
            case PMEnableMetallicID:
               enableMetallic( data->boolData( ) );
               break;
            case PMEnableReflectionID:
               enableReflection( data->boolData( ) );
               break;
            case PMEnableExponentID:
               enableExponent( data->boolData( ) );
               break;
            default:
               kdError( PMArea ) << "Wrong ID in PMFinish::restoreMemento\n";
               break;
         }
      }
   }
   Base::restoreMemento( s );
}
