/*********************************************************
**
**   title:       Jesy
**   description: JS framework for creating JS based
**                applications
**
**   varsion:     0.1
**
*/


Jesy = {};
Jesy.VERSION    = '0.1.1';


/*************************************
*
*           Constants
*
**************************************/
Jesy._base_class_file       = 'Jesy.js';
Jesy._modules_class_file    = 'Jesy/Modules.js';
Jesy.BASE_MODULES           = ['Jesy.Event', 'Jesy.Object', 'Jesy.Compat'];



/*************************************
*
*           Browser Check
*
**************************************/
Jesy.isIE            = false;
Jesy.isMozilla       = false;
Jesy.isKonqueror     = false;
Jesy.isSafari        = false;
Jesy.isOpera         = false;
Jesy.isOmniWeb       = false;
Jesy.isWebTV         = false;
Jesy.isiCab          = false;
Jesy.isNS            = false;


Jesy._checkBrowserName = function ( string ) {
    return navigator.userAgent.toLowerCase().indexOf( string ) + 1;
}


// TODO: make it a little bit more correct
if ( Jesy._checkBrowserName('konqueror'))        Jesy.isKonqueror = true;
else if (Jesy._checkBrowserName('safari'))       Jesy.isSafari    = true;
else if (Jesy._checkBrowserName('omniweb'))      Jesy.isOmniWeb   = true;
else if (Jesy._checkBrowserName('opera'))        Jesy.isOpera     = true;
else if (Jesy._checkBrowserName('webtv'))        Jesy.isWebTV     = true;
else if (Jesy._checkBrowserName('icab'))         Jesy.isiCab      = true;
else if (Jesy._checkBrowserName('msie'))         Jesy.isIE        = true;
else if (!Jesy._checkBrowserName('compatible'))  Jesy.isNS        = true;



//
//  Error handling
//
Jesy._error = function ( msg ) {
    alert('Jesy Error: ' + msg )
}


/*************************************
*
*  Jesy.Request
*
**************************************/
Jesy.Request = function ( args ){
    args = args || {};

    this._sync      = args.sync   || false;
    this._url       = args.url;
    this._org_url   = args.url;
    this._method    = args.method || Jesy.Request.D_METHOD;
    this._type      = args.type   || Jesy.Request.T_HTML;
    this._args      = {};
    this.onReady    = null;

    this.init();
}

Jesy.Request.D_METHOD       = 'GET';
Jesy.Request.COMPLETE       = 4;

// response codes
Jesy.Request.OK             = 200;
Jesy.Request.NOT_MODIFYED   = 304;

Jesy.Request.T_HTML         = 'html';
Jesy.Request.T_JSON         = 'json';
Jesy.Request.T_JS           = 'js';


Jesy.Request.prototype.init = function () {
    try {
        this._req = new ActiveXObject("Msxml2.XMLHTTP")
    }
    catch(ex) {
        try {
            this._req = new ActiveXObject("Microsoft.XMLHTTP");
        }
        catch (ex1) {
            this._req = null;
        }
    }

    if( ! this._req && typeof XMLHttpRequest != "undefined" ){
        this._req = new XMLHttpRequest()
    }

    if ( this._req == null ){
        Jesy._error("Can't create XMLHttpRequest object")
    }
}


Jesy.Request.prototype.url = function( url ) {
    if ( url != null ){
        this._url       = url;
        this._org_url   = url;
    }

    return this._url;
}


Jesy.Request.prototype.change_state = function( ) {
    if ( this._req.readyState == Jesy.Request.COMPLETE ){

        var state = this._req.status;
        if ( state == null || ( state != Jesy.Request.OK && state != Jesy.Request.NOT_MODIFYED ) ){
            Jesy._error("Error retrieving [" + this._url + "]\nRemote status:" + this._req.status );
        }

        this._text = this._req.responseText;

        if ( this.onReady != null ){
            this.onReady();
        }
    }
}


Jesy.Request.prototype.exec = function( ) {

    // prepare request
    this.prepare();

    this._req.open(this._method, this._url , ! this._sync );

    // assign handler only if connection is not sync
    if ( ! this._sync ){
        var req = this;
        this._req.onreadystatechange = function () { req.change_state() };
    }

    this._req.send(null)

    // call ready state handler manyally because connection is sync
    if ( this._sync ){
        this.change_state();
    }

    if ( this._type != Jesy.Request.T_HTML ){
        if ( this._type == Jesy.Request.T_JSON ){
            // transform JSON to object
            try {
                var res = eval( '(' + this._text + ')' );
                return res;
            } catch( ex ){
                Jesy._error(" Can't transform JSON to object: " + ex )
            }
        }


        if ( this._type == Jesy.Request.T_JS ){
            // eva returned JS code
            try {
                eval( this._text );
                return;
            } catch( ex ){
                Jesy._error(" Error processing Jesy.Request : " + ex )
            }
        }
    }

    return this._text;
}


Jesy.Request.prototype.getText = function( ) {
    return this._text;
}


Jesy.Request.prototype.param = function( args ){
    args = args || {};

    for ( var key in args ){
        this._args[key] = args[key];
    }
}


Jesy.Request.prototype.reset = function (){
    this._args      = {};
}


Jesy.Request.prototype.prepare = function (){
    // because for now we support only GET method we'll form request URL with all params
    var args        = Jesy.Array();
    var separator   = this._org_url.match(/\?/) ? '&' : '?';

    for ( var k in this._args ){
        var val     = this._args[k];

        if ( val == null )
            continue;

        if ( typeof val == 'object' && val.length != null ){
            var ordered = k.match(/\[\]/) ? false : true;

            for ( var i=0; i < val.length; i++ ){
                var cur_key = k;
                if ( ordered ){
                    cur_key = k + "[" + i + "]";
                }

                args.push( encodeURIComponent(cur_key) + "=" + encodeURIComponent(val[i]) );
            }
        }else{
            args.push( encodeURIComponent(k) + "=" + encodeURIComponent(val) );
        }
    }

    this._url = this._org_url + separator + args.join("&");
}


/*************************************
*
*        Files Manipulation
*
**************************************/
Jesy._include = function ( file ){
    var request;
    var res = { success: false };

    if ( file == null ){
        Jesy._error('Jesy._include: file not passed')
        return res;
    }

    try {
        request = new ActiveXObject("Msxml2.XMLHTTP")
    }
    catch(ex) {
        try {
            request = new ActiveXObject("Microsoft.XMLHTTP");
        }
        catch (ex1) {
            request = null;
        }
    }

    if( ! request && typeof XMLHttpRequest != "undefined" ){
        request = new XMLHttpRequest()
    }

    request.open('GET', file , false );
    request.send(null);

    if ( request.status != null && ( request.status != 200 && ! ( request.status == 304 && Jesy.isKonqueror ) ) ){
        return res;
    }

    res.success = true;
    res.code    = request.responseText;

    return res;
}



/*************************************
*
*           Jesy Modules
*
**************************************/
Jesy._path = null;

Jesy._getScriptDir = function ( path ) {
    // remove domain portion of the path
    path = path.replace(/^http(s)?:\/\/.*?\//, '/')

    // remove script file
    path = path.replace(/\w+\.js/, '')

    if ( path == '' )
        path = './'

    return path;
}


Jesy._includeModules = function () {
    // get path of all scripts
    var scripts = document.getElementsByTagName('SCRIPT');

    for ( var i=0; i < scripts.length; i++ ){
        if ( scripts[i].src.match(Jesy._base_class_file) ){
            Jesy._path = Jesy._getScriptDir( scripts[i].src );
        }
    }

    if ( Jesy._path == null ){
        Jesy._error( "Can't find base path" );
        return;
    }

    // first include Jesy::Modules
    var modules_file = Jesy._path + Jesy._modules_class_file;
    var res = Jesy._include( modules_file )

    if ( ! res.success ){
        Jesy._error("Can't include file: " + modules_file + "\nFile not found." );
        return;
    }

    // eval the code
    try {
        eval(res.code)
    }
    catch (ex){
        Jesy._error("Can't include file: " + modules_file + "\n" + ex );
    }

    for ( var i=0; i < Jesy.BASE_MODULES.length; i++ ){
        Jesy.use( Jesy.BASE_MODULES[i] )
    }
}



// include all Jesy base modules
Jesy._includeModules();

