/************************************************************************ 
  Copyright 2011-2012, IceJS Team. All rights reserved.
  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are
  met:
  
      * Redistributions of source code must retain the above copyright
        notice, this list of conditions and the following disclaimer.
      * Redistributions in binary form must reproduce the above
        copyright notice, this list of conditions and the following
        disclaimer in the documentation and/or other materials provided
        with the distribution.
      * Neither the name of Update Freezer Team nor the names of its
        contributors may be used to endorse or promote products derived
        from this software without specific prior written permission.
  
  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ***********************************************************************/

/**
 * @fileOverview
 * This is a wrapper for IO functions.
 *
 * Attribute like @[description] used here to generate help.chm file.
 */
 
if (typeof(Util) == "undefined")
	Util = {};

/**
 * Object that represent IO functions.
 * @class Util.IO
 */
Util.IO = 
{
	/**
	 * Return text contents of file by its path.
	 * @param fileName Path to file.
	 * @returns File content.
	 */
	ReadFile: function(/**String*/ fileName) /**String*/
	{
		return _ReadFile(fileName);
	},
	
	/**
	 * Return text contents of file by its path, assuming it has UTF8 encoding
	 * @param fileName Path to file
	 * @returns File content.
	 */
	ReadFileUTF8: function(/**String*/ fileName) /**String*/
	{
		return _ReadFileUTF8(fileName);	
	},
	
	/**
	 * Write text contents to a file by its path. Will create new file.
	 * @param fileName Path to file.
	 * @param text Text to write.
	 * @returns Boolean. True if success
	 */
	WriteFile: function(/**String*/ fileName, /**String*/ text) /**Boolean*/
	{
		return _WriteFile(fileName, text);
	},
	
	/**
	 * Write text contents to a file by its path. Will create new file. Will use UTF8 encoding to write.
	 * @param fileName Path to file.
	 * @param text Text to write.
	 * @returns Boolean. True if success
	 */
	WriteFileUtf8: function(/**String*/ fileName, /**String*/ text) /**Boolean*/
	{
		return _WriteFileUTF8(fileName, text);
	},

	/**
	 * Returns 'true' when file exists
	 * @param fileName Path to file.
	 * @returns Boolean. True if exists
	 */
	CheckFileExists: function(/**String*/ fileName) /**Boolean*/
	{
		return _CheckFileExists(fileName);
	},
	
	/**
	 * Returns 'true' when directory exists
	 * @param path Path to directory.
	 * @returns Boolean. True if exists
	 */
	CheckDirectoryExists: function(/**String*/ path) /**Boolean*/
	{
		return _CheckFileExists(path);
	},
	
	/**
	 * Delete a file with path specified by 'fileName'
	 * @param fileName Path to file.
	 * @returns Boolean. True if success
	 */
	DeleteFile: function(/**String*/ fileName) /**Boolean*/
	{
		return _DeleteFile(fileName);
	},
	
	/**
	 * Copy a file with path specified by 'src' to a file specified by 'dst'
	 * @param src Path to file to copy.
	 * @param dst Path to destination file.
	 * @returns Boolean. True if success
	 */
	CopyFile: function(/**String*/ src, /**String*/ dst) /**Boolean*/
	{
		var dstParent = Util.IO.GetParentFolder(dst);
		
		if(dstParent&&!Util.IO.CheckFileExists(dstParent))
		{
			Util.IO.CreateDirectory( dstParent );
		}
	
		return _CopyFile(src, dst);
	},
	
	/**
	 * Move a file with path specified by 'src' to a file specified by 'dst'
	 * @param src Path to file to move.
	 * @param dst Path to destination file.
	 * @returns Boolean. True if success
	 */
	MoveFile: function(/**String*/ src, /**String*/ dst) /**Boolean*/
	{
		return _MoveFile(src, dst);
	},
	
	/**
	 * Create directory with specified path
	 * @param path Path to directory to create.
	 * @returns Boolean. True if success
	 */
	CreateDirectory: function(/**String*/ path) /**Boolean*/
	{
		return _EnsureDirectoryExists(path);
	},
	
	/**
	 * Delete directory with specified path
	 * @param path Path to directory to delete.
	 * @returns Boolean. True if success
	 */
	DeleteDirectory: function(/**String*/ path) /**Boolean*/
	{
		return _RemoveDirectoryWithContents(path);
	},
	
	/**
	 * Combine path
	 * @param path1 Path.
	 * @param path2 Path.
	 * @returns String.
	 */
	CombinePath: function(/**String*/ path1, /**String*/ path2)
	{
		// Trim trailing separators in path1
		path1 = path1.replace(new RegExp("[\\/\\\\]+$", "g"), "");
		return path1+"\\"+path2;
	},
		
	/**
	 * Return folder name if 'path' represents a folder or file name if 'path' represents file.
	 * @param path Path.
	 * @returns String.
	 */
	GetLastPathComponent: function(/**String*/ path) /**String*/
	{
		// Trim trailing separators in path1
		path = path.replace(new RegExp("[\\/\\\\]+$", "g"), "");
		path = path.replace("/", "\\");
		var parts = path.split("\\");
		
		if( parts && parts.length>0 )
		{
			return parts[parts.length-1];
		}
		return "";
	},
	
	/**
	 * For path like c:\a/b/c/d return c:\a/b/c (without trailing separator)
	 * for 'd' being either folder or file.
	 * @param path Path.
	 * @returns Parent folder path. String.
	 */
	GetParentFolder: function(/**String*/ path) /**String*/
	{
		path = path.replace(new RegExp("[\\/\\\\]+$", "g"), "");
		
		for(var li=path.length-1;li--;li>=0)
		{
			var c = path.charAt(li);
			if(c=='\\'||c=='/')
			{
				path = path.substr(0, li);
				path = path.replace(new RegExp("[\\/\\\\]+$", "g"), "");
				return path;
			}
		}
		return "";
	},
	
	/**
	 * Read key input from console
	 * @returns Char pressed
	 */
	ReadKey: function()
	{
		return _ReadKey();
	},
	
	/**
	 * Get current directory
	 * @returns Path of current directory or false.
	 */
	GetCurrentDirectory: function() /**String*/
	{
		return _GetCurrentDirectory();
	},
	
	/**
	 * Set current directory
	 * @param newDir Directory path to set.
	 * @returns Boolean. True if success
	 */
	SetCurrentDirectory: function(/**String*/ newDir) /**Boolean*/
	{
		return _SetCurrentDirectory(newDir);
	},
	
	/**
	 * Get file name from its path
	 * @param p Path.
	 * @returns File name or false if error.
	 */
	GetFileName: function(/**String*/ p) /**String*/
	{
		return _GetFileName(p);
	},
	
	/**
	 * Get file path from its path
	 * @param p Path.
	 * @returns Full file path or false if error.
	 */
	GetFilePath: function(/**String*/ p) /**String*/
	{
		return _GetFilePath(p);
	},
	
	/**
	 * Read JSON object from file by its path
	 * @param fileName Path.
	 * @returns Object. Null if error
	 */
	ReadJsonFromFile: function(/**String*/ fileName) /**Object*/
	{
		var text = Util.IO.ReadFile(fileName);
		var obj = null;
		try
		{
			obj = JSON.parse(text);
		}
		catch(e)
		{
		
		}
		return obj;
	},
	
	/**
	 * Write JSON object to file
	 * @param fileName Path.
	 * @param obj Object to write.
	 */
	WriteJsonToFile: function(/**String*/ fileName, /**Object*/ obj)
	{
		var text = JSON.stringify(
						obj,
						function(key, value){
							if(typeof key==="string" && key.indexOf("parent")==0 || key=="rule") return undefined;
							return value;
						},
						"\t"
					);
		this.WriteFile(fileName, text);
	},
	
	/**
	 * Enum files in folder
	 * @param path Path to folder.
	 * @returns Array
	 */
	GetFilesInFolder: function(/**String*/ path) /**Array*/
	{
		return _GetFilesInFolder(path);
	},
	
	/**
	 * Enum sub folders in folder
	 * @param path Path to folder.
	 * @returns Array
	 */
	GetSubFolders: function(/**String*/ path) /**Array*/
	{
		return _GetSubFolders(path);
	},	
	
	/**
	 * Create shortcut
	 * @param targetFile Path to destination file.
	 * @param arguments Arguments to launch.
	 * @param workingDir Path to working folder.
	 * @param shortcutPath Shortcut path.
	 * @param shortcutComment Shortcut comment.
	 * @param iconLocation Path to icon.
	 * @param iconIndex Icon index.
	 * @returns Boolean. True if success
	 */
	CreateShortcut: function(/**String*/targetFile, /**String*/arguments, /**String*/workingDir, /**String*/shortcutPath, /**String*/shortcutComment, /**String*/iconLocation, /**Number*/iconIndex)
	{
		return _CreateShortcut(targetFile, arguments, workingDir, shortcutPath, shortcutComment, iconLocation, iconIndex);
	},
	
	/**
	 * Apply shift bytes coding to a string
	 * @param str Original string.
	 * @param shift Number of bytes to shift.
	 * @returns String with shifted bytes.
	 */
	ShiftBytes: function(/**String*/str, /**Number*/shift) /**String*/
	{
		return _ShiftBytes(str, shift);
	},
	
	/**
	 * Apply shift bytes coding to a f1 file.
	 * @param f1 Original file path.
	 * @param f2 Shifted file path.
	 * @param shift Number of bytes to shift.
	 * @returns Boolean. True if success
	 */
	ShiftFileBytes: function(/**String*/ f1, /**String*/ f2, /**Number*/ shift) /**Boolean*/
	{
		return _ShiftFileBytes(f1, f2, shift);
	}
}
