/* ****************************************************************************
  This file is part of KBabel

  Copyright (C) 1999-2000 by Matthias Kiefer
                            <matthias.kiefer@gmx.de>
		2001-2002 by Stanislav Visnovsky
			    <visnovsky@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.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

  In addition, as a special exception, the copyright holders give
  permission to link the code of this program with any edition of
  the Qt library by Trolltech AS, Norway (or with modified versions
  of Qt that use the same license as Qt), and distribute linked
  combinations including the two.  You must obey the GNU General
  Public License in all respects for all of the code used other than
  Qt. If you modify this file, you may extend this exception to
  your version of the file, but you are not obligated to do so.  If
  you do not wish to do so, delete this exception statement from
  your version.

**************************************************************************** */

#include "gettextexport.h"

#include <resources.h>
#include "catalog.h"
#include "catalogitem.h"
#include "catalogsettings.h"

#include <qfile.h>
#include <qtextcodec.h>

#include <kapplication.h>
#include <kdebug.h>
#include <kgenericfactory.h>

K_EXPORT_COMPONENT_FACTORY( kbabel_gettextexport, KGenericFactory<GettextExportPlugin> )

using namespace KBabel;

GettextExportPlugin::GettextExportPlugin(QObject* parent, const char* name, const QStringList &) :
    CatalogExportPlugin(parent,name)
{
}

ConversionStatus GettextExportPlugin::save(const QString& localFile , const QString& mimetype, const Catalog* catalog)
{
   // check, whether we know how to handle the extra data
   if( catalog->importPluginID() != "GNU gettext") 
      return UNSUPPORTED_TYPE;

   // we support on the application/x-gettext MIME type
   if( mimetype != "application/x-gettext") 
      return UNSUPPORTED_TYPE;

   QFile file(localFile);

   if(file.open(IO_WriteOnly))
   {
      int progressRatio = QMAX(100/ QMAX(catalog->numberOfEntries(),1), 1);
      emit signalResetProgressBar(i18n("saving file"),100);

      QTextStream stream(&file);
      
      SaveSettings _saveSettings = catalog->saveSettings();
      
      if(_saveSettings.useOldEncoding && catalog->fileCodec())
      {
	    stream.setCodec(catalog->fileCodec());
      }
      else
      {
         switch(_saveSettings.encoding)
         {
            case ProjectSettingsBase::UTF8:
               stream.setCodec(QTextCodec::codecForName("utf-8"));
               break;
            case ProjectSettingsBase::UTF16:
               stream.setCodec(QTextCodec::codecForName("utf-16"));
               break;
            default:
	       stream.setCodec(QTextCodec::codecForLocale());
               break;
         }
      }

      // only save header if it is not empty
      if(!catalog->header().comment().isEmpty() || !catalog->header().msgstr().isEmpty())
      {
	 // write header
	  if(!catalog->header().comment().isEmpty())
	  {
	      stream << catalog->header().comment() << "\n";
	  }

	  QString str = catalog->header().msgid().first();	       
	  QStringList list=QStringList::split("\n",str);

	  if(str.left(1)=="\n")
		list.prepend("");

	  if(list.isEmpty())
		list.append("");

	  QValueList<QString>::ConstIterator lit;
	  
	  // if the msgid has more than one line
	  if(list.count() > 1)
		list.prepend("");

	  stream << "msgid ";
	  for( lit = list.begin(); lit != list.end(); ++lit )
	  {
		stream << "\"" << (*lit) << "\"\n";
	  }
	  
	  str = catalog->header().msgstr().first();

	  list=QStringList::split("\n",str);
	  
	  if(str.left(1)=="\n")
		list.prepend("");
		
	  if(list.isEmpty())
		list.append("");

    	  // if the msgstr has more than one line
    	  if(list.count() > 1)
        	list.prepend("");

    	  stream << "msgstr ";
    	  for( lit = list.begin(); lit != list.end(); ++lit )
    	  {
        	stream << "\"" << (*lit) << "\"\n";
    	  }

         stream << "\n";
      }

      QStringList list;
      for( uint counter = 0; counter < catalog->numberOfEntries() ; counter++ )
      {
          if(counter%10==0) {
             emit signalProgress(counter/progressRatio);
	  }
	  
	  // write entry
	  const QString comment = catalog->comment(counter);
	  if(!comment.isEmpty())
	  {
              // We must check that each comment line really starts with a #, to avoid syntax errors
              int pos = 0;
              for(;;)
              {
                  const int newpos = comment.find( '\n', pos, false );
                  if ( newpos == pos )
                  {
                    ++pos;
                    stream << "\n";
                    continue;
                  }
                  const QString span ( ( newpos == -1 ) ? comment.mid( pos ) : comment.mid( pos, newpos-pos ) );
                  
                  const int len = span.length();
                  for ( int i = 0 ; i < len ; ++i )
                  {
                      const QChar& ch = span[ i ];
                      if ( ch == '#' )
                      {
                          stream << span.mid( i );
                          break;
                      }
                      else if ( ch == ' ' || ch == '\t' )
                      {
                          stream << ch;
                      }
                      else
                      {
                          stream << "# " << span.mid( i );
                          break;
                      }
                  }
                  stream << "\n";

                  if ( newpos == -1 )
                      break;
                  else
                      pos = newpos + 1;
              }
	  }

	  if(!catalog->msgctxt(counter).isEmpty())
	  {
		QStringList list=msgctxtAsList(catalog, counter);
		QValueList<QString>::ConstIterator lit;

		// if the msgctxt has more than one line
		if(list.count() > 1)
		  list.prepend("");

		stream << "msgctxt ";
		for( lit = list.begin(); lit != list.end(); ++lit )
		{
		  stream << "\"" << (*lit) << "\"\n";
		}
	  }

	  QStringList list=msgidAsList(catalog, counter);
	  QValueList<QString>::ConstIterator lit;
	  
	  // if the msgid has more than one line
	  if(list.count() > 1)
		list.prepend("");

	  stream << "msgid ";
	  for( lit = list.begin(); lit != list.end(); ++lit )
	  {
		stream << "\"" << (*lit) << "\"\n";
	  }
	  
	  if( catalog->pluralForm(counter) == Gettext)
	  {
		list = msgidAsList(catalog, counter,true);
    		// if the msgid has more than one line
    		if(list.count() > 1)
        	    list.prepend("");

    		stream << "msgid_plural ";
    		for( lit = list.begin(); lit != list.end(); ++lit )
    		{
        	    stream << "\"" << (*lit) << "\"\n";
    		}
	  }
	  
	  if( catalog->pluralForm(counter) != Gettext)
	  {
		list=msgstrAsList(catalog, counter);
    		// if the msgstr has more than one line
    		if(list.count() > 1)
        	    list.prepend("");

    		stream << "msgstr ";
    		for( lit = list.begin(); lit != list.end(); ++lit )
    		{
        	    stream << "\"" << (*lit) << "\"\n";
    		}
	  }
	  else
	  {
		kdDebug(KBABEL) << "Saving gettext plural form" << endl;
    		int forms = catalog->msgstr(counter).count();
    		for(int i=0; i<forms; i++)
    		{
        	    list=msgstrAsList(catalog, counter, i);
        	    // if the msgstr has more than one line
        	    if(list.count() > 1)
            		list.prepend("");

        	    stream << "msgstr[" << i << "] ";
        	    for( lit = list.begin(); lit != list.end(); ++lit )
        	    {
            		stream << "\"" << (*lit) << "\"\n";
        	    }
    		}
	  }
	  
          stream << "\n";

	 kapp->processEvents(10);
	 if( isStopped() )
	 {
	    return STOPPED;
	 }
      }

      if( _saveSettings.saveObsolete )
      {
          QValueList<QString>::ConstIterator oit;
	  
	  QStringList _obsolete = catalog->catalogExtraData();

          for( oit = _obsolete.begin(); oit != _obsolete.end(); ++oit )
    	  {
              stream << (*oit) << "\n\n";

	      kapp->processEvents(10);
	      if( isStopped() )
	      {
		  return STOPPED;
	      }
          }
      }
      
      emit signalProgress(100);
      file.close();

      emit signalClearProgressBar();
   }
   else
   {
      //emit signalError(i18n("Wasn't able to open file %1").arg(filename.ascii()));
      return OS_ERROR;
   }

   return OK;
}

QStringList GettextExportPlugin::msgctxtAsList(const Catalog* catalog, uint item) const
{
   QString str = catalog->msgctxt(item);

   QStringList list=QStringList::split("\n",str);
			  
   if(str.left(1)=="\n")
	list.prepend("");
				   
   if(list.isEmpty())
	list.append("");

   return list;
}

QStringList GettextExportPlugin::msgidAsList(const Catalog* catalog, uint item, bool plural) const
{
   QString str;
   if( catalog->pluralForm(item) == Gettext && plural)
	str = catalog->msgid(item).last();
   else
	str = catalog->msgid(item).first();
		       
   QStringList list=QStringList::split("\n",str);
			  
   if(str.left(1)=="\n")
	list.prepend("");
				   
   if(list.isEmpty())
	list.append("");

   return list;
}

QStringList GettextExportPlugin::msgstrAsList(const Catalog* catalog, uint item, uint nr) const
{
   QString str;
   
   if(catalog->pluralForm(item) == Gettext && nr > 0)
   {
	if( nr > catalog->msgstr(item).count() )
	{
	    kdWarning(KBABEL) << "request for non existing plural form " << nr << endl;
	}
	else
	{
	    str = *(catalog->msgstr(item).at(nr));
	}
   }
   else
   {
	str = catalog->msgstr(item).first();
   }

   QStringList list=QStringList::split("\n",str);

   if(str.left(1)=="\n")
	list.prepend("");

   if(list.isEmpty())
	list.append("");

   return list;
}
