/*
Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.
For licensing, see LICENSE.html or http://ckeditor.com/license
*/

importPackage( java.util.regex );
importClass( java.text.SimpleDateFormat );

( function()
{
	/*
	 * An array with missing keys in current translation.
	 */
	var missingKeys;

	CKLANGTOOL.gettext = function()
	{
		return {
			run : function()
			{
				var children = CKLANGTOOL.languageDir.list();
				var file, poFile;
				var foundFiles = false;

				metaInformation = loadMetaInformation();

				if ( CKLANGTOOL.enhancedComments )
					loadSourceTranslationIntoMeta();

				for ( var i = 0 ; i < children.length ; i++ )
				{
					if ( CKLANGTOOL.io.getExtension( children[ i ] ) != "js" || children[ i ].indexOf( '_' ) == 0 )
						continue;

					file = new File( CKLANGTOOL.languageDir, children[ i ] );
					if ( file.isFile() )
					{
						poFile =  new File( CKLANGTOOL.destinationDir, children[i].replaceAll( '.js', '.po' ) );
						print( "Processing " + file.getAbsolutePath() );

						CKLANGTOOL.io.saveFile( poFile, processFile(file), false );
						foundFiles = true;
					}
				}

				if ( !foundFiles )
				{
					print( "WARNING: language files not found." );
				}

				print( "Process completed." );
			}
		};
	};

	/**
	 * Meta file stores an extra information about each string (context, user friendly description).
	 * The format is:
	 * fieldId = information
	 * 
	 * Sample entry:
	 * link.noUrl = Error message shown to the user when URL field is empty.
	 */
	function loadMetaInformation()
	{
		if (!CKLANGTOOL.metaFile)
			return {};

		var lines = CKLANGTOOL.io.readFileIntoArray(CKLANGTOOL.metaFile);
		var meta = {};

		for ( var j = 0 ; j < lines.length ; j++ )
		{
			var line = lines[ j ];
			if ( match = line.match( /^\s*([a-z0-9_.]+)\s*=\s*(.*)\s*$/i ) )
			{
				meta[match[1]] = match[2];
			}
		}
		return meta;
	}

	/**
	 * Loads source translation to "meta" array.
	 */
	function loadSourceTranslationIntoMeta()
	{
		/**
		 * Helper function, adds object to the "meta array"
		 * @param prefix
		 * @param o
		 */
		var addToMetaInformation = function( prefix, o )
		{
			var result = [];

			for ( var key in o )
			{
				var entry = o[ key ],
					entryName = prefix ? ( prefix + '.' + key ) : key;

				if ( typeof entry == 'object' )
					addToMetaInformation( entryName, entry );
				else
				{
					if ( !metaInformation[entryName] )
						metaInformation[entryName] = "Source string: \n#. " + entry.replace( /\n/g,  "#. ");
					else
						metaInformation[entryName] += "\n#. \n#. Source string: \n#. " + entry.replace( /\n/g,  "#. ");
				}
			}
		}

		var result = CKLANGTOOL.loadLanguageFile( CKLANGTOOL.templateFile );
		addToMetaInformation( '', result.translation );
	}

	function printObject( prefix, o )
	{
		var result = [];

		for ( var key in o )
		{
			var entry = o[ key ],
				entryName = prefix ? ( prefix + '.' + key ) : key;

			if ( typeof entry == 'object' )
				result.push( printObject( entryName, entry ) );
			else
				result.push( poEntry( entryName, entry ) );
		}
		
		return result.join( '' );
	}

	function msgstrEscape( str )
	{
		return str.replace( /"/g, '\\"' ).replace( /\r\n|\n/g, '\\n"$&"' );
	}

	/**
	 *  Generate a PO translation entry with the following schematic structure:
	 *	whte-space
	 *	# translator-comments
	 *	#.extracted-comments
	 *	#:reference...
	 *	#,flag...
	 *	#|msgid previous-untranslated-string
	 *	msid untranslated-string
	 *	msstr translated-string
	 *
	 * @param {String} id The untranslated string part.
	 * @param {String} str The translated-string part.
	 * @param {String} [ comment1, comment2... ] Translator comments.
	 */
	function poEntry( id, str, comment )
	{
		var entry = [];
		var comments = Array.prototype.slice.call( arguments, 2 );
		for ( var i = 0; i < comments.length; i++ )
			entry.push( comments[ i ] );
		if ( metaInformation[id] )
			entry.push( '#. ' + metaInformation[id] );
		if ( missingKeys[id] ) {
			str = "";
		}
		entry.push( 'msgid "' + id + '"', 'msgstr "' + msgstrEscape( str ) + '"', '\n' );
		return entry.join( '\n' );
	}

	function processFile( file )
	{
		function poHeader()
		{
			var now = new SimpleDateFormat("yyyy-MM-dd HH:mmZ").format( new java.util.Date());
			var headers = [
			'"Project-Id-Version: CKEditor\\n"',
			'"Report-Msgid-Bugs-To: http://dev.ckeditor.com/newticket\\n"',
			'"POT-Creation-Date: 2011-05-31 00:00+0000\\n"',
			'"PO-Revision-Date: ' + now + '\\n"',
			'"Last-Translator: CKEditor\\n"',
			'"Language-Team: CKEditor translation team\\n"',
			'"MIME-Version: 1.0\\n"',
			'"Content-Type: text/plain; charset=UTF-8\\n"',
			'"Content-Transfer-Encoding: 8bit\\n"',
			'"Language: ' + language.languageCode + '\\n"',
			'"Plural-Forms: nplurals=2; plural=(n != 1)\\n"',
			'\n'
			].join( '\n' );

			return new java.lang.String( poEntry( '', '', license, overview ) ).trim() + '\n' + headers;
		}

		// License Info
		var fileInfo = CKLANGTOOL.analyzeLanguageFile( file );
		var date = new Date(),
			license = '# Copyright (c) 2003-' + date.getFullYear() + ', CKSource - Frederico Knabben. All rights reserved.\n# For licensing, see LICENSE.html or http://ckeditor.com/license';
		var overview = '#' + fileInfo.fileOverviewBlock.replace( /\{.*?\}/g, '' ).replace( /@fileOverview/g, '' ).replace(/\s*(\/)?\s*(\*)+(\/)?/g , '').replace(/\s+/g, ' ');

		missingKeys = fileInfo.missingKeys;

		var language = CKLANGTOOL.loadLanguageFile( file, 'json' );
		return poHeader() + printObject( '', language.translation );
	}

})();
