/*
**************************************************************************
                                 description
                             --------------------
    copyright            : (C) 2000-2003 by Andreas Zehender
    email                : zehender@kde.org
**************************************************************************

**************************************************************************
*                                                                        *
*  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 "pmoutputdevice.h"
#include "pmpovrayformat.h"
#include <tqtextstream.h>
#include <tdelocale.h>

unsigned int PMOutputDevice::s_indentOffset = 3;
bool PMOutputDevice::s_bracketBehindType = true;

PMOutputDevice::PMOutputDevice( TQIODevice* dev, PMPovrayFormat* format )
      : PMSerializer( dev ), m_stream( dev )
{
   m_pFormat = format;
   m_indentation = 0;
   m_lastWasComment = false;
   m_pendingNewLine = false;
   m_objectSeparation = false;
}

PMOutputDevice::~PMOutputDevice( )
{
}

TQString PMOutputDevice::description( ) const
{
   return TQString( "POV-Ray" );
}

void PMOutputDevice::callSerialization( const PMObject* o, const PMMetaObject* mo )
{
   if( !mo )
      return;

   const PMPovraySerializeMethodInfo* info =
      m_pFormat->serializationMethod( mo->className( ) );

   if( info )
      info->call( o, mo, this );
   else
   {
      if( mo == o->metaObject( ) )
      {
         printError( i18n( "The object \"%1\" doesn't support %2." )
                     .arg( o->description( ) ).arg( description( ) ) );
      }
      else
      {
         printError( i18n( "The class \"%1\" doesn't support %2." )
                     .arg( o->description( ) ).arg( mo->className( ) ) );
      }
   }
}

void PMOutputDevice::serialize( PMObject* o )
{
   callSerialization( o, o->metaObject( ) );
}

void PMOutputDevice::close( )
{
//   m_stream << ( char ) 0;
}

void PMOutputDevice::objectBegin( const TQString& type )
{
   if( m_pendingNewLine )
      newLine( );
   if( m_objectSeparation )
      newLine( );
   m_stream << type;
   if( s_bracketBehindType )
      m_stream << " ";
   else
      newLine( );

   m_stream << "{";
   m_indentation++;
   m_indentString.fill( ' ', s_indentOffset * m_indentation );
   m_pendingNewLine = true;
   m_objectSeparation = false;
}

void PMOutputDevice::declareBegin( const TQString& id )
{
   if( m_pendingNewLine )
      newLine( );
   if( m_objectSeparation )
      newLine( );
   m_stream << "#declare " << id << " = ";

   m_objectSeparation = false;
}

void PMOutputDevice::objectEnd( )
{
   m_indentation--;
   m_indentString.fill( ' ', s_indentOffset * m_indentation );
   newLine( );
   m_stream << "}";
   m_pendingNewLine = true;
   m_objectSeparation = true;
}

void PMOutputDevice::writeLine( const TQString& str )
{
   if( m_pendingNewLine )
      newLine( );
   m_stream << str;
   m_pendingNewLine = true;
   m_objectSeparation = true;
}

void PMOutputDevice::write( const TQString& str )
{
   if( m_pendingNewLine )
      newLine( );
   m_stream << str;
   m_objectSeparation = false;
}

void PMOutputDevice::newLine( )
{
   m_lastWasComment = false;
   m_pendingNewLine = false;
   m_stream << '\n' << m_indentString;
}

void PMOutputDevice::writeComment( const TQString& text )
{
   TQString s( text );
   TQTextStream str( &s, IO_ReadOnly );

   bool lwc = m_lastWasComment;
   if( m_pendingNewLine )
      newLine( );
   if( lwc )
      newLine( );
   if( m_objectSeparation )
      newLine( );
   if( str.atEnd( ) )
      writeLine( "//" );
   else
      while( !str.atEnd( ) )
         writeLine( TQString( "// " ) + str.readLine( ) );
   m_lastWasComment = true;
   m_objectSeparation = false;
}

void PMOutputDevice::writeSemicolon( )
{
   // does not change m_pendingNewLine!
   m_stream << ';';
}

void PMOutputDevice::writeName( const TQString& name )
{
   if( !name.isEmpty( ) )
      writeLine( TQString( "//*PMName " ) + name );
}

TQString PMOutputDevice::escapeAndQuoteString( const TQString& s )
{
   TQString result = "\"";
   TQString tmp = s;
   TQTextStream stream( &tmp, IO_ReadOnly );
   TQChar current, last;

   while( !stream.atEnd( ) )
   {
      stream >> current ;
      // not escaped quotation mark
      if( ( current == '"' ) && ( last != '\\' ) )
         result += '\\';
      result += current;
      // correctly quoted backslash
      if( ( last == '\\' ) && ( current == '\\' ) )
         current = TQChar( 0 ); // clear the last char
      last = current;
   }
   // backslash at the end
   if( last == '\\' )
      result += '\\';
   result += '"';

   return result;
}