/* -------------------------------------------------------------------------- */
/*  Helix JavaScript Library - Version 1.0                                    */
/*                                                                            */
/*  @file: helix.js                                                           */
/*                                                                            */
/*  @desc: Helix library                                                      */
/*                                                                            */
/*  @requires: Dojo Javascript library :  http://dojotoolkit.org              */
/* -------------------------------------------------------------------------- */

/* ------------------------------------------------ */
/* the root variable(s) of helix public symbols     */
/* ------------------------------------------------ */

  var helix    = {};  /* root of everything         */

  helix.widget = {};  /* for widgets                */
  helix.bionux = {};  /* for bionux                 */

/* ------------------------------------------------ */
/* helix module registration                        */
/* ------------------------------------------------ */

  dojo.registerModulePath("helix", "../helix/src");

/* ------------------------------------------------ */
/* dojo requirements                                */
/* ------------------------------------------------ */
  
  dojo.require("dojo.io.*");
  dojo.require("dojo.json");
  dojo.require("dojo.Deferred");

/* ------------------------------------------------ */
/* dojo io extensions                               */
/* ------------------------------------------------ */

  helix.json = {

  /* ------------------------------------------------ */
  /* load json data (at url) using GET (default)      */
  /* please consider using helix.jow.load instead     */
  
    get: function (url) {
      var jsonData;
      var request = dojo.io.bind({
        url: url,
        method: "get",
        mimetype: "text/json",
        sync: "true",
        load: function(type, data, evt) {
                jsonData = data; },
        error: function(type, data, evt) {
                dojo.debug("can't get Json : " + url); }
        });
        return jsonData;
      },

  /* ------------------------------------------------ */
  /* post and load raw json data (at url) using POST  */
  /* contentObj : a json object to post               */

		post: function (url, contentObj) {
			var jsonData;
			var request = dojo.io.bind({
				url: url,
				method: "post",
				mimetype: "text/json",
				contentType: "text/plain",
				postContent: 	dojo.json.serialize(contentObj),
				sync: "true",
				load: function(type, data, evt) {
								jsonData = data; },
				error: function(type, data, evt) {
								dojo.debug("can't post Json : " + url); }
				});
				return jsonData;
			}
      
  };

/* ------------------------------------------------ */
/* JOW (Json Object Wrapper) library                */
/* ------------------------------------------------ */

  helix.jow = {
  
  /* ------------------------------------------------ */
  /* placeholder for regular expression recognizing   */
  /* JOW objects types                                */
  
      _JowREObj: new RegExp("^(([^:]+:)*object:)([^:]+)$"),
  
  /* ------------------------------------------------ */
  /* match RE exp against value                       */
  
      matchExp: function(exp, value) {
        return (exp && value && (new RegExp(exp, "i")).test(value));
      },
  
  /* ------------------------------------------------ */
  /* check JOW type                                   */
      
      checkType: function(obj, type) {
        if (! (obj && obj.type))
          return false;  // no type or data for object
        if (! type)
          return true;   // undefined type should match any type
        var oType = this._splitType(obj.type);
        var tType = this._splitType(type);
        return this.matchExp("^" + tType.type + "(:.*)?$", oType.type)
           &&  this.matchExp("\\." + (tType.clas || ".*") + "\\.", 
                             "." + (oType.clas || "") + ".");
      },
  
  /* ------------------------------------------------ */
  /* split JOW type into {type: type, clas: class     */
  
      // internal utility
      
      _splitType: function(type) {
        var match = this._JowREObj.exec(type);
        return (match ? {type: match[1], clas: match[3]} : {type: type});
      },
  
      // API
      
      splitType: function(obj) {
        if (! (obj && obj.type))
          return {};
        return this._splitType(obj.type);
      },
  
  /* ------------------------------------------------ */
  /* load JOW data (at url), check expected type      */
  /* (if provided) and return JOW error if any.       */
  /* get: use the GET method                          */
  /* post: use the POST method                        */
      
      // internal utility

      _postLoad: function(reply, url, type) {
      
        if (! this.checkType(reply)) {
          dojo.debug("invalid JOW object " + url);
          return { type: "error",
                   message: "invalid JOW object at " + url,
                   data: reply };
        }
        
        if (this.checkType(reply, "error")) {
          dojo.debug("got an error object " + url);
          return reply;
        }
        
        if (! this.checkType(reply, type)) {
          dojo.debug("incorrect type for JOW object " + url);
          return { type: "error",
                   message: "bad type for JOW object at " + url, 
                   details: "expected type: " + type + "\n" +
                            "declared type: " + (reply.type || "<none>"),
                   data: reply };
        }
  
        return reply;
      },
      
      // API
      
      get: function(url, expectedType) {
      
        var reply = helix.json.get(url);
        
        return this._postLoad(reply, url, expectedType);
      },

      // API
      
      post: function(url, contentObj, expectedType) {
      
        var reply = helix.json.post(url, contentObj);

        return this._postLoad(reply, url, expectedType);
      }

  };

/* ------------------------------------------------ */
/* dojo deferred extension                          */
/* ------------------------------------------------ */

/* ------------------------------------------------ */
/* simple deferred with callback and opt errback    */

  helix.newDeferred = function(cb, eb) {
    var deferred = new dojo.Deferred();
    if (cb) deferred.addCallback(cb);
    if (eb) deferred.addErrback(eb);
    return deferred;
  };

/* ------------------------------------------------ */
/* dojo widgets extensions                          */
/* ------------------------------------------------ */

/* ------------------------------------------------ */
/* create a new (unused) id for widget              */
  
  helix.widget.newId = function (prefix) {
    var localPrefix = prefix || "wgt";
    var id, i = 0;
    do {
      id = localPrefix + "_" + (i++);
    } while (dojo.widget.getWidgetById(id) != null);
    return id;
  };

/* ------------------------------------------------ */
/* get the widget domNode                           */

  helix.widget.domNode = function(id) {
    var elt = document.getElementById(id);
    if (elt) return elt;
    elt = dojo.widget.byId(id);
    if (elt) return elt.domNode;
    // return is undefined
  };




