/*----------------------------------------------------------------

Class: adobe

Properties:
console - undefined
debugging - boolean
options - hash
version - string
COLOR_DEPTH - number or NaN
DIR - string
FILE - string
PATH - string
SCRIPT_BUILD - number or NaN
SCRIPT_ENGINE - string
SCRIPT_VERSION - number or NaN

Author: 
btapley

----------------------------------------------------------------*/

var adobe = Class.create({
	initialize: function(options) {
		var src = document.getElementById("adobe").getAttribute("src"),
		lastfolder = src.lastIndexOf("/"),
		folders = src.substring(0, lastfolder),
		file = src.substring(lastfolder+1),
		q = src.split("?")[1],
		options = options || {},
		NAN = parseInt("");

		if(q) { Object.extend(options, q.toQueryParams()); }

		this.version = "0.1";
		this.options = options;
		this.debugging = false;
		this.console;
		this.DIR = folders;
		this.PATH = folders+"/";
		this.FILE = file;
		this.COLOR_DEPTH = screen.colorDepth || NAN;
		this.SCRIPT_ENGINE = (window.ScriptEngine) ? window.ScriptEngine() : "JavaScript";
		this.SCRIPT_VERSION = (this.SCRIPT_ENGINE == "JScript") ? (ScriptEngineMajorVersion()+ScriptEngineMinorVersion()/10) : NAN;
		this.SCRIPT_BUILD = (this.SCRIPT_ENGINE == "JScript") ? ScriptEngineBuildVersion() : NAN;
	},
/*----------------------------------------------------------------	

	Method: debug
	Set to true, this provides <Console> methods in the adobe object eg. adobe.log

>	adobe.debug(true)

	Parameters:
	bool - boolean
	
	Returned Value:
	Nothing

----------------------------------------------------------------*/
	debug: function(bool) {
		if(this.debugging === bool) {return;}
		this.debugging = !!bool;
		adobe.Jsan.errorLevel = (this.debugging) ? "die" : "none";
		adobe.Jsan.use("adobe.Console");
		var console = new adobe.Console();		
		Object.extend(this, console);
	}
});

adobe = new adobe();

/*----------------------------------------------------------------	

	JSAN implementation

----------------------------------------------------------------*/

adobe.Jsan = function () { adobe.Jsan.addRepository(arguments) }

adobe.Jsan.VERSION = 0.10;

adobe.Jsan.globalScope   = self;
adobe.Jsan.includePath   = ['.', 'lib'];
adobe.Jsan.errorLevel    = "none";
adobe.Jsan.errorMessage  = "";
adobe.Jsan.loaded        = {};

adobe.Jsan.use = function () {
    var classdef = adobe.Jsan.require(arguments[0]);
    if (!classdef) return null;

    var importList = adobe.Jsan._parseUseArgs.apply(adobe.Jsan, arguments).importList;
    adobe.Jsan.exporter(classdef, importList);

    return classdef;
}

adobe.Jsan.require = function (pkg) {
    var path = adobe.Jsan._convertPackageToPath(pkg);
    if (adobe.Jsan.loaded[path]) {
        return adobe.Jsan.loaded[path];
    }

    try {
        var classdef = eval(pkg);
        if (typeof classdef != 'undefined') return classdef;
    } catch (e) { /* nice try, eh? */ }


    for (var i = 0; i < adobe.Jsan.includePath.length; i++) {
        var js;
        try{
            var url = adobe.Jsan._convertPathToUrl(path, adobe.Jsan.includePath[i]);
                js  = adobe.Jsan._loadJSFromUrl(url);
        } catch (e) {
            if (i == adobe.Jsan.includePath.length - 1) throw e;
        }
        if (js != null) {
            var classdef = adobe.Jsan._createScript(js, pkg);
            adobe.Jsan.loaded[path] = classdef;
            return classdef;
        }
    }
    return false;

}

adobe.Jsan.exporter = function () {
    adobe.Jsan._exportItems.apply(adobe.Jsan, arguments);
}

adobe.Jsan.addRepository = function () {
    var temp = adobe.Jsan._flatten( arguments );
    // Need to go in reverse to do something as simple as unshift( @foo, @_ );
    for ( var i = temp.length - 1; i >= 0; i-- )
        adobe.Jsan.includePath.unshift(temp[i]);
    return adobe.Jsan;
}

adobe.Jsan._flatten = function( list1 ) {
    var list2 = new Array();
    for ( var i = 0; i < list1.length; i++ ) {
        if ( typeof list1[i] == 'object' ) {
            list2 = adobe.Jsan._flatten( list1[i], list2 );
        }
        else {
            list2.push( list1[i] );
        }
    }
    return list2;
};

adobe.Jsan._convertPathToUrl = function (path, repository) {
    return repository.concat('/' + path);
};
    

adobe.Jsan._convertPackageToPath = function (pkg) {
    var path = pkg.replace(/\./g, '/');
        path = path.concat('.js');
    return path;
}

adobe.Jsan._parseUseArgs = function () {
    var pkg        = arguments[0];
    var importList = [];

    for (var i = 1; i < arguments.length; i++)
        importList.push(arguments[i]);

    return {
        pkg:        pkg,
        importList: importList
    }
}

adobe.Jsan._loadJSFromUrl = function (url) {
    return new adobe.Jsan.Request().getText(url);
}

adobe.Jsan._findExportInList = function (list, request) {
    if (list == null) return false;
    for (var i = 0; i < list.length; i++)
        if (list[i] == request)
            return true;
    return false;
}

adobe.Jsan._findExportInTag = function (tags, request) {
    if (tags == null) return [];
    for (var i in tags)
        if (i == request)
            return tags[i];
    return [];
}

adobe.Jsan._exportItems = function (classdef, importList) {
    var exportList  = new Array();
    var EXPORT      = classdef.EXPORT;
    var EXPORT_OK   = classdef.EXPORT_OK;
    var EXPORT_TAGS = classdef.EXPORT_TAGS;
    
    if (importList.length > 0) {
       importList = adobe.Jsan._flatten( importList );

       for (var i = 0; i < importList.length; i++) {
            var request = importList[i];
            if (   adobe.Jsan._findExportInList(EXPORT,    request)
                || adobe.Jsan._findExportInList(EXPORT_OK, request)) {
                exportList.push(request);
                continue;
            }
            var list = adobe.Jsan._findExportInTag(EXPORT_TAGS, request);
            for (var i = 0; i < list.length; i++) {
                exportList.push(list[i]);
            }
        }
    } else {
        exportList = EXPORT;
    }
    adobe.Jsan._exportList(classdef, exportList);
}

adobe.Jsan._exportList = function (classdef, exportList) {
    if (typeof(exportList) != 'object') return null;
    for (var i = 0; i < exportList.length; i++) {
        var name = exportList[i];

        if (adobe.Jsan.globalScope[name] == null)
            adobe.Jsan.globalScope[name] = classdef[name];
    }
}

adobe.Jsan._makeNamespace = function(js, pkg) {
    var spaces = pkg.split('.');
    var parent = adobe.Jsan.globalScope;
    eval(js);
    var classdef = eval(pkg);
    for (var i = 0; i < spaces.length; i++) {
        var name = spaces[i];
        if (i == spaces.length - 1) {
            if (typeof parent[name] == 'undefined') {
                parent[name] = classdef;
                if ( typeof classdef['prototype'] != 'undefined' ) {
                    parent[name].prototype = classdef.prototype;
                }
            }
        } else {
            if (parent[name] == undefined) {
                parent[name] = {};
            }
        }

        parent = parent[name];
    }
    return classdef;
}

adobe.Jsan._handleError = function (msg, level) {
    if (!level) level = adobe.Jsan.errorLevel;
    adobe.Jsan.errorMessage = msg;

    switch (level) {
        case "none":
            break;
        case "warn":
            alert(msg);
            break;
        case "die":
        default:
            throw new Error(msg);
            break;
    }
}

adobe.Jsan._createScript = function (js, pkg) {
    try {
        return adobe.Jsan._makeNamespace(js, pkg);
    } catch (e) {
        adobe.Jsan._handleError("Could not create namespace[" + pkg + "]: " + e);
    }
    return null;
}


adobe.Jsan.prototype = {
    use: function () { adobe.Jsan.use.apply(adobe.Jsan, arguments) }
};


// Low-Level HTTP Request
adobe.Jsan.Request = function (jsan) {
    if (adobe.Jsan.globalScope.XMLHttpRequest) {
        this._req = new XMLHttpRequest();
    } else {
        this._req = new ActiveXObject("Microsoft.XMLHTTP");
    }
};

adobe.Jsan.Request.prototype = {
    _req:  null,
    
    getText: function (url) {
        this._req.open("GET", url, false);
        try {
            this._req.send(null);
            if (this._req.status == 200 || 
		this._req.status == 0)
                return this._req.responseText;
        } catch (e) {
            adobe.Jsan._handleError("File not found: " + url);
            return null;
        };

        adobe.Jsan._handleError("File not found: " + url);
        return null;
    }
};

Object.extend(adobe, {
/*----------------------------------------------------------------	

	Method: use

>	adobe.use("adobe.foo")

	Parameters:
	namespace - string
	
	Returned Value:
	Class reference
	
	Delegate for:
	<http://www.openjsan.org/src/c/cw/cwest/JSAN-0.08/doc/html/JSAN.html>

----------------------------------------------------------------*/
	use: adobe.Jsan.use,
/*----------------------------------------------------------------	

	Method: addRepository
	
>	adobe.addRepository("/path/to/repository");
	
	Parameters:
	path - string
	
	Returned Value:
	JSAN Object reference
	
	Delegate for:
	<http://www.openjsan.org/src/c/cw/cwest/JSAN-0.08/doc/html/JSAN.html>

----------------------------------------------------------------*/
	addRepository: adobe.Jsan.addRepository,
/*----------------------------------------------------------------	

	Method: setLoaded

>	adobe.setLoaded(adobe.foo, adobe.PATH+"adobe/foo.js")

	Parameters:
	module - object reference
	file - string
	
	Returned Value:
	None
	
	Delegate for:
	<http://www.openjsan.org/src/c/cw/cwest/JSAN-0.08/doc/html/JSAN.html>

----------------------------------------------------------------*/
	setLoaded: function(module, file) {
		adobe.Jsan.loaded[file] = module;
	}
});

adobe.addRepository(adobe.DIR);
adobe.setLoaded(adobe, adobe.FILE);

/*----------------------------------------------------------------	

	Asset Linking

----------------------------------------------------------------*/

adobe.use("adobe.Loader");

Object.extend(adobe, {
/*----------------------------------------------------------------	

	Method: link
	
>	adobe.link("path/to/file.css", {media:"screen"})
	
	Parameters:
	path - relative path from adobe.js file as string
	params - hash
	
	Returned Value:
	0 = Nothing, 1 = Done, 2 = Error

----------------------------------------------------------------*/
	link: adobe.Loader.requireAsset.wrap(function($proceed, path, params) {
		$proceed(adobe.PATH + path, params);	
	}),
/*----------------------------------------------------------------	

	Method: setLinked

>	adobe.setLinked("/path/to/file.css")

	Parameters:
	path - relative path from adobe.js file as string
	
	Returned Value:
	None

----------------------------------------------------------------*/
	setLinked: adobe.Loader.setLoaded.wrap(function($proceed, path) {
		$proceed(adobe.PATH + path);
	})
});