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

importPackage( javax.activation );
importPackage( com.ice.tar );

importClass( java.io.BufferedReader );
importClass( java.io.BufferedWriter );
importClass( java.io.FileWriter );
importClass( java.io.FileOutputStream );
importClass( java.io.FileInputStream );
importClass( java.io.InputStreamReader );
importClass( java.io.FileOutputStream );
importClass( java.io.OutputStreamWriter );
importClass( java.util.zip.ZipOutputStream );
importClass( java.util.zip.ZipEntry );
importClass( java.util.zip.GZIPInputStream );

( function()
{
	var txtExtensions =
	{
		"" : 0,
		"afp" : 1,
		"afpa" : 1,
		"ascx" : 1,
		"asp" : 1,
		"aspx" : 1,
		"bat" : 1,
		"cfc" : 1,
		"cfm" : 1,
		"cgi" : 1,
		"code" : 1,
		"command" : 1,
		"conf" : 1,
		"css" : 1,
		"dtd" : 1,
		"htaccess" : 1,
		"htc" : 1,
		"htm" : 1,
		"html" : 1,
		"js" : 1,
		"jsp" : 1,
		"lasso" : 1,
		"php" : 1,
		"pl" : 1,
		"py" : 1,
		"readme" : 1,
		"sample" : 1,
		"sh" : 1,
		"txt" : 1,
		"xml" : 1
	};

	function compressDirectory( sourcePath, outStream, compressMethod, rootDir )
	{
		if ( CKRELEASER.verbose )
			print( "    " + compressMethod + ": " + sourcePath );

		if ( !rootDir )
			rootDir = "";

		var r = new File( CKRELEASER.releaseDir );

		try
		{
			var compressedDir = new File( sourcePath );

			var dirList = compressedDir.list();
			var readBuffer = new Packages.java.lang.reflect.Array.newInstance( java.lang.Byte.TYPE, 2056 );
			var bytesIn = 0;
			var anEntry, fis;

			for ( var i = 0 ; i < dirList.length ; i++ )
			{
				var f = new File( compressedDir, dirList[i] );

				if ( f.isDirectory() )
				{
					compressDirectory( f.getPath(), outStream, compressMethod, rootDir );
					continue;
				}

				fis = new FileInputStream( f );

				switch ( compressMethod )
				{
					case 'tar.gz' :
						anEntry = new TarEntry( f.getCanonicalPath().replace( r.getCanonicalPath(), rootDir ).replace( "\\", "/" ) );
						break;
					case 'zip' :
						anEntry = new ZipEntry( f.getCanonicalPath().replace( r.getCanonicalPath(), rootDir ).replace( "\\", "/" ) );
						break;
					default:
						throw "Unknown compression method: " + compressMethod;
						break;
				}

				outStream.putNextEntry( anEntry );

				while ( ( bytesIn = fis.read( readBuffer ) ) != -1 )
				{
					outStream.write( readBuffer, 0, bytesIn );
				}
				outStream.closeEntry();

				fis.close();
			}
		}
		catch ( e )
		{
			throw "An error occured during (" + compressMethod + ") compression of " + sourcePath + ": " + e;
		}
	}

	function copyFile( sourceLocation, targetLocation )
	{
		try
		{
			var inStream = new FileInputStream( sourceLocation );
			var outStream = new FileOutputStream( targetLocation );

			var len, buf = new Packages.java.lang.reflect.Array.newInstance( java.lang.Byte.TYPE, 1024 );

			while ( ( len = inStream.read( buf ) ) != -1 )
			{
				outStream.write( buf, 0, len );
			}
			inStream.close();
			outStream.close();
		}
		catch ( e )
		{
			throw "Cannot copy file:\n Source: " + sourceLocation.getCanonicalPath() + "\n Destination : "
					+ targetLocation.getCanonicalPath() + "\n" + e.message;
		}
	}

	CKRELEASER.io =
	{
		copyFile : copyFile,

		deleteDirectory : function( path )
		{
			var dir = new File( path );

			if ( dir.isDirectory() )
			{
				var children = dir.list();
				for ( var i = 0 ; i < children.length ; i++ )
				{
					if ( !this.deleteDirectory( new File( dir, children[i] ) ) )
					{
						return false;
					}
				}
			}

			return dir["delete"]();
		},

		deleteFile : function( path )
		{
			var f = new File( path );

			if ( !f.exists() )
				return true;

			if ( !f.canWrite() )
				throw "Cannot delete file: " + f.getAbsolutePath();

			return f["delete"]();
		},

		saveFile : function( file, text, includeBom )
		{
			try
			{
				var stream = new BufferedWriter( new OutputStreamWriter( new FileOutputStream( file ), "UTF-8" ) );
				if ( includeBom )
					stream.write( 65279 );
				stream.write( text );
				stream.flush();
				stream.close();
			}
			catch ( e )
			{
				throw "Cannot save file:\n Path: " + file.getCanonicalPath() + "\n Eception details: " + e.message;
			}
		},

		copy : function( sourceLocation, targetLocation, extraIgnoredPaths )
		{
			if ( CKRELEASER.release.isIgnoredPath( sourceLocation.getAbsolutePath(), extraIgnoredPaths ) )
				return;

			if ( CKRELEASER.verbose )
				print( "    Copy -> " + targetLocation.toString().replaceFirst( ".*?release(/|\\\\)?", '' ) );

			if ( sourceLocation.isDirectory() )
			{
				if ( !targetLocation.exists() )
				{
					targetLocation.mkdir();
				}

				var children = sourceLocation.list();
				for ( var i = 0 ; i < children.length ; i++ )
				{
					this.copy( new File( sourceLocation, children[i] ), new File( targetLocation, children[i] ), extraIgnoredPaths );
				}

				if ( !targetLocation.list().length )
				{
					targetLocation['delete']();
				}
			}
			else
			{
				copyFile( sourceLocation, targetLocation );
			}
		},

		zipDirectory : function( sourcePath, targetFile, rootDir )
		{
			var outStream = new ZipOutputStream( new FileOutputStream( targetFile ) );
			compressDirectory( sourcePath, outStream, "zip", rootDir );
			outStream.close();
		},

		targzDirectory : function( sourcePath, targetFile, rootDir )
		{
			var outStream = new TarGzOutputStream( new FileOutputStream( targetFile ) );
			compressDirectory( sourcePath, outStream, "tar.gz", rootDir );
			outStream.close();
		},

		setByteOrderMark : function( file, includeUtf8Bom )
		{
			var buffer = new StringBuffer();
			var chars = new Packages.java.lang.reflect.Array.newInstance( java.lang.Character.TYPE, 32 );
			var count;

			try
			{
				var inStream = new InputStreamReader( new FileInputStream( file ), "UTF-8" );
			}
			catch ( e )
			{
				throw 'An I/O error occurred while opening the ' + file + ' file.';
			}

			try
			{
				count = inStream.read( chars, 0, 32 );

				if ( count <= 0 )
					return;

				buffer.append( chars, 0, count );

				/* BOM is at the beginning of file */
				if ( buffer.length() && buffer.charAt( 0 ) == 65279 )
				{
					if ( !includeUtf8Bom )
					{
						if ( CKRELEASER.verbose )
							print( "Removing BOM from " + file.getCanonicalPath() );
						this.saveFile( file, this.readFile( file ) );
					}
				}
				else
				{
					if ( includeUtf8Bom )
					{
						if ( CKRELEASER.verbose )
							print( "Adding BOM to " + file.getCanonicalPath() );
						this.saveFile( file, this.readFile( file ), true );
					}
				}
			}
			catch ( e )
			{
				throw 'An I/O error occurred while reading the ' + file.getCanonicalPath() + ' file.';
			}
			finally
			{
				inStream.close();
			}
		},

		/**
		 * Reads file and returns file contents without initial UTF-8 Byte Order
		 * Mark
		 */
		readFile : function( file )
		{
			var buffer = new StringBuffer();
			var chars = new Packages.java.lang.reflect.Array.newInstance( java.lang.Character.TYPE, 8192 );
			var count;

			if ( !file.exists() )
			{
				throw 'File ' + file + ' does not exist.';
			}

			try
			{
				var inStream = new InputStreamReader( new FileInputStream( file ), "UTF-8" );
			}
			catch ( e )
			{
				throw 'An I/O error occurred while opening the ' + file + ' file.';
			}

			try
			{
				while ( ( count = inStream.read( chars, 0, 8192 ) ) != -1 )
				{
					if ( count > 0 )
					{
						buffer.append( chars, 0, count );
					}
				}
			}
			catch ( e )
			{
				throw 'An I/O error occurred while reading the ' + file.getCanonicalPath() + ' file.';
			}
			finally
			{
				inStream.close();
			}

			/* http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4508058 */
			if ( buffer.length() && buffer.charAt( 0 ) == 65279 )
				buffer.deleteCharAt( 0 );

			return String( buffer.toString() );
		},

		getDirectoryInfo : function( file )
		{
			var path_iterator, current_file, files, result =
			{
				files : 0,
				size : 0
			};

			if ( !file.exists() )
				return result;

			files = file.listFiles();

			if ( !files )
				return result;

			path_iterator = ( java.util.Arrays.asList( files ) ).iterator();

			while ( path_iterator.hasNext() )
			{
				current_file = path_iterator.next();
				if ( current_file.isFile() )
				{
					result.size += current_file.length();
					result.files++;
				}
				else
				{
					var info = this.getDirectoryInfo( current_file );
					result.size += info.size;
					result.files += info.files;
				}
			}

			return result;
		},

		getFileName : function( filePath )
		{
			var file = new File( filePath );
			return file.getName();
		},

		getExtension : function( fileName )
		{
			var pos = fileName.lastIndexOf( "." );
			if ( pos == -1 )
				return "";
			else
				return String( fileName.substring( pos + 1 ).toLowerCase() );
		},

		isTextFile : function( fileName )
		{
			var ext = this.getExtension( fileName );

			return txtExtensions[ext] === 1;
		},

		isChildPath : function( childPath, parentPath )
		{
			if ( childPath.length > parentPath.length )
				return false;

			var i = 0, max = Math.min( childPath.length(), parentPath.length() );

			while ( i < max && childPath.charAt( i ) == parentPath.charAt( i ) )
				i++;

			return i != max;
		}
	};
} )();
