/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is JIM.
 *
 * The Initial Developer of the Original Code is
 * Pawel Chmielowski <prefiks@o2.pl>
 *
 * Portions created by the Initial Developer are Copyright (C) 2003
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 * Pawel Chmielowski <prefiks@o2.pl>
 *
 * ***** END LICENSE BLOCK ***** */

/**
 * io.File
 *
 *
 */
ML.load('io/reader.js');

/**
 * File
 *
 * Constructor:
 *   File(path, encoding [, subpath, ...])
 *
 * Fields:
 *   size
 *   exists
 *   path
 *
 * Methods:
 *   open(mode, perms)
 *   read([len])
 *   write(data)
 *   remove();
 *   flush()
 *   close()
 *
 */

function File(path)
{
    const classes = Components.classes;
    const interfaces = Components.interfaces;
    var uri, i;
    var ios = Components.classes["@mozilla.org/network/io-service;1"].
        getService(Components.interfaces.nsIIOService);

    this.base = Reader;

    try {
        this.file = classes["@mozilla.org/file/local;1"].
            createInstance(interfaces.nsILocalFile);

        if (path.search(/\w+:\/\//) == -1) {
            this.file.initWithPath(path);

            for (i = 1; i < arguments.length; i++)
                this.file.append(arguments[i]);

            this.uri = ios.newFileURI(this.file);
        } else {
            this.base(arguments);
                this.file.initWithPath(this.uri.
                    QueryInterface(interfaces.nsIFileURL).file.path);
        }
    } catch (ex) {
        throw new IOException("file.unable_to_create_file_object", ex);
    }

    this.path = this.file.path;
}

File.prototype =
{
    MODE_RDONLY   : 0x01,
    MODE_WRONLY   : 0x02,
    MODE_RDWR     : 0x04,
    MODE_CREATE   : 0x08,
    MODE_APPEND   : 0x10,
    MODE_TRUNCATE : 0x20,
    MODE_SYNC     : 0x40,
    MODE_EXCL     : 0x80,

    __proto__: Reader.prototype,

    open: function(mode, charset, perms)
    {
        const classes = Components.classes;
        const interfaces = Components.interfaces;
        var is, bs;

        this.setCharset(charset);

        if (typeof perms == "undefined")
            perms = 0666;

        if (mode & (this.MODE_WRONLY | this.MODE_RDWR))
        {
            try {
                this.__outputStream = 
                    classes["@mozilla.org/network/file-output-stream;1"].
                    createInstance(interfaces.nsIFileOutputStream);
                this.__outputStream.init(this.file, mode, perms, false);
            } catch (ex) {
                throw new IOException("file.unable_to_create_output_stream", ex);
            }
        }
        
        if (mode & (this.MODE_RDONLY | this.MODE_RDWR))
        {
            try {
                is = classes["@mozilla.org/network/file-input-stream;1"].
                    createInstance(interfaces.nsIFileInputStream);
                this.__bufferedStream = classes["@mozilla.org/network/buffered-input-stream;1"].
                    createInstance(interfaces.nsIBufferedInputStream);
                this.__inputStream = classes["@mozilla.org/scriptableinputstream;1"].
                    createInstance(interfaces.nsIScriptableInputStream);

                this.__bufferedStream.QueryInterface(Components.interfaces.nsISeekableStream);

                is.init(this.file, mode, perms, false);
                this.__bufferedStream.init(is, 8192);
                this.__inputStream.init(this.__bufferedStream);
            } catch (ex) {
                throw new IOException("file.unable_to_create_input_stream", ex);
            }

        }    
    },

    write: function(data)
    {
        if (this.__coder)
            data = this.__coder.encode(data);
        try {
            return this.__outputStream.write(data, data.length);
        } catch (ex) {
            throw new IOException("file.write_error", ex);
        }
    },

    close: function()
    {
        if ("__outputStream" in this)
            this.__outputStream.close();
        if ("__inputStream" in this)
            this.__inputStream.close();
        this.__inputStream = this.__outputStream = null;
    },

    remove: function(recursive)
    {
        if (!this.exist)
            return;
        try {
            this.close();
            this.file.remove(recursive);
        } catch (ex) {
            throw new IOException("file.unable_to_remove_file", ex);
        }
    },

    flush: function()
    {
        if (this.__outputStream)
            this.__outputStream.flush();
    },

    createDirectory: function(perms)
    {
        try {
            this.file.create(1, perms);
        } catch (ex) {
            throw new IOException("file.unable_to_create_directory", ex);
        }
    },

    get exists ()
    {
        return this.file.exists();
    },

    get size()
    {
        return this.file.fileSize;
    },
}