/**
  *
  *  Copyright 2005 Sabre Airline Solutions
  *
  *  Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
  *
  *  Unless required by applicable law or agreed to in writing, software distributed under the
  *  License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
  *  either express or implied. See the License for the specific language governing permissions
  *  and limitations under the License.
  **/

// NOTE: This file differs from the original version as ricoAjaxEngine.js is also included below
 
var Rico = {
  Version: '2.0 rc2',
  loadRequested: 1,
  loadComplete: 2,
  init : function() {
    try {  // fix IE background image flicker (credit: www.mister-pixel.com)
      document.execCommand("BackgroundImageCache", false, true);
    } catch(err) {}
    this.preloadMsgs='';
    var elements = document.getElementsByTagName('script');
    this.baseHref= location.protocol + "//" + location.host;
    this.loadedFiles={};
    this.windowIsLoaded=false;
    this.onLoadCallbacks=[];
    for (var i=0; i<elements.length; i++) {
      if (!elements[i].src) continue;
      var src = elements[i].src;
      var slashIdx = src.lastIndexOf('/');
      var path = src.substring(0, slashIdx+1);
      var filename = src.substring(slashIdx+1);
      this.loadedFiles[filename]=this.loadComplete;
      var parmPos  = filename.indexOf('?');
      if (parmPos > 0)
        filename = filename.substring(0, parmPos)
      if (filename == 'rico.js') {
        var isRailsPath = (path.indexOf("/javascripts") > 0)
        if (isRailsPath){
          this.jsDir = "/javascripts/";
          this.cssDir = "/stylesheets/";
          this.imgDir = "/images/";
          this.htmDir = "/";
          this.xslDir = "/";
        } else {
          this.jsDir = path;
          this.cssDir = path+'css/';
          this.imgDir = path+'images/';
          this.htmDir = path;
          this.xslDir = path;
        }
      }
    }
    if (typeof Prototype=='undefined') this.include('protoculous-effects-shrinkvars.js');
    //this.include('ricoCommon.js');
    //this.languageInclude('en');   // in case a phrase is missing from a translation
    this.acceptLanguage(navigator.language || navigator.userLanguage);
    var onloadAction=function() { Rico.windowLoaded(); };
    if (window.addEventListener)
      window.addEventListener('load', onloadAction, false);
    else if (window.attachEvent)
      window.attachEvent('onload', onloadAction);
    this.onLoad(function() { Rico.writeDebugMsg('Pre-load messages:\n'+Rico.preloadMsgs); });
  },

  // Array entries can reference a javascript file or css stylesheet
  // A dependency on another module can be indicated with a plus-sign prefix: '+DependsOnModule'
  moduleDependencies : {
    Accordion  : ['ricoBehaviors.js','ricoEffects.js','ricoComponents.js'],
    Color      : ['ricoColor.js','ricoStyles.js'],
    Corner     : ['ricoStyles.js'],
    DragAndDrop: ['ricoStyles.js','ricoEffects.js','ricoDragDrop.js'],
    Effect     : ['ricoEffects.js'],
    Calendar   : ['ricoCalendar.js', 'ricoCalendar.css'],
    Tree       : ['ricoTree.js', 'ricoTree.css'],
    ColorPicker: ['ricoColorPicker.js', 'ricoStyles.js', 'ricoColorPicker.css'],
    CustomMenu : ['ricoMenu.js', 'ricoMenu.css'],
    SimpleGrid : ['+Effect', 'ricoGridCommon.js', 'ricoGrid.css', 'ricoSimpleGrid.js'],
    LiveGridBasic : ['ricoGridCommon.js', 'ricoGrid.css', 'ricoBehaviors.js', 'ricoLiveGrid.js'],
    LiveGrid      : ['+Effect', '+LiveGridBasic', 'ricoLiveGridControls.js'],
    LiveGridMenu  : ['+CustomMenu', 'ricoLiveGridMenu.js'],
    LiveGridAjax  : ['+LiveGrid', 'ricoLiveGridAjax.js'],
    LiveGridJSON  : ['+LiveGridAjax', 'ricoLiveGridJSON.js'],
    LiveGridForms : ['+LiveGridAjax', '+LiveGridMenu', '+Accordion', '+Corner', 'ricoLiveGridForms.js', 'ricoLiveGridForms.css'],
    SpreadSheet   : ['+SimpleGrid', 'ricoSheet.js', 'ricoSheet.css']
  },
  
  languages : {
    de: "translations/ricoLocale_de.js",
    en: "translations/ricoLocale_en.js",
    es: "translations/ricoLocale_es.js",
    fr: "translations/ricoLocale_fr.js",
    it: "translations/ricoLocale_it.js",
    ja: "translations/ricoLocale_ja.js",
    ko: "translations/ricoLocale_ko.js",
    pt: "translations/ricoLocale_pt.js",
    zh: "translations/ricoLocale_zh.js"
  },
  
  languageInclude : function(lang2) {
    var filename=this.languages[lang2];
    if (filename) this.include(filename);
    return !!filename;
  },
  
  acceptLanguage : function(acceptLang) {
    var arLang=acceptLang.toLowerCase().split(',');
    for (var i=0; i<arLang.length; i++) {
      var lang2=arLang[i].match(/\w\w/);
      if (!lang2) continue;
      if (this.languageInclude(lang2)) return true;
    }
    return false;
  },

  // Expects one or more module or file names
  loadModule : function() {
    for (var a=0, length=arguments.length; a<length; a++) {
      var name=arguments[a];
      var dep=this.moduleDependencies[name];
      if (dep) {
        for (var i=0; i<dep.length; i++)
          if (dep[i].substring(0,1)=='+')
            this.loadModule(dep[i].slice(1));
          else
            this.include(dep[i]);
      } else {
        this.include(name);
      }
    }
  },

  include : function(filename) {
    if (this.loadedFiles[filename]) return;
    this.addPreloadMsg('include: '+filename);
    var ext = filename.substr(filename.lastIndexOf('.')+1);
    switch (ext.toLowerCase()) {
      case 'js':
        this.loadedFiles[filename]=filename.substring(0,4)=='rico' ? this.loadRequested : this.loadComplete;
        document.write("<script type='text/javascript' src='"+this.jsDir+filename+"'><\/script>");
        return;
      case 'css':
        var el = document.createElement('link');
        el.type = 'text/css';
        el.rel = 'stylesheet'
        el.href = this.cssDir+filename;
        this.loadedFiles[filename]=this.loadComplete;
        document.getElementsByTagName('head')[0].appendChild(el);
        return;
    }
  },

  // called after a script file has finished loading
  includeLoaded: function(filename) {
    this.loadedFiles[filename]=this.loadComplete;
    this.checkIfComplete();
  },

  // called by the document onload event
  windowLoaded: function() {
    this.windowIsLoaded=true;
    this.checkIfComplete();
  },

  checkIfComplete: function() {
    var waitingFor=this.windowIsLoaded ? '' : 'window';
    for(var filename in  this.loadedFiles) {
      if (this.loadedFiles[filename]==this.loadRequested)
        waitingFor+=' '+filename;
    }
    //window.status='waitingFor: '+waitingFor;
    this.addPreloadMsg('waitingFor: '+waitingFor);
    if (waitingFor.length==0) {
      this.addPreloadMsg('Processing callbacks');
      while (this.onLoadCallbacks.length > 0) {
        var callback=this.onLoadCallbacks.shift();
        if (callback) callback();
      }
    }
  },

  onLoad: function(callback,frontOfQ) {
    if (frontOfQ)
      this.onLoadCallbacks.unshift(callback);
    else
      this.onLoadCallbacks.push(callback);
    this.checkIfComplete();
  },

  isKonqueror : navigator.userAgent.toLowerCase().indexOf("konqueror") >= 0,

  // logging funtions

  startTime : new Date(),

  timeStamp: function() {
    var stamp = new Date();
    return (stamp.getTime()-this.startTime.getTime())+": ";
  },

  setDebugArea: function(id, forceit) {
    if (!this.debugArea || forceit) {
      var newarea=document.getElementById(id);
      if (!newarea) return;
      this.debugArea=newarea;
      newarea.value='';
    }
  },

  addPreloadMsg: function(msg) {
    this.preloadMsgs+=Rico.timeStamp()+msg+"\n";
  },

  writeDebugMsg: function(msg, resetFlag) {
    if (this.debugArea) {
      if (resetFlag) this.debugArea.value='';
      this.debugArea.value+=this.timeStamp()+msg+"\n";
    }
    else if (window.console) window.console.log(this.timeStamp()+msg);
    else if (window.opera) window.opera.postError(this.timeStamp()+msg);
  }

}

Rico.init();


//-------------------- ricoAjaxEngine.js
Rico.AjaxEngine = Class.create();

Rico.AjaxEngine.prototype = {

   initialize: function() {
      this.ajaxElements = new Array();
      this.ajaxObjects  = new Array();
      this.requestURLS  = new Array();
      this.options = {};
   },

   registerAjaxElement: function( anId, anElement ) {
      if ( !anElement )
         anElement = $(anId);
      this.ajaxElements[anId] = anElement;
   },

   registerAjaxObject: function( anId, anObject ) {
      this.ajaxObjects[anId] = anObject;
   },

   registerRequest: function (requestLogicalName, requestURL) {
      this.requestURLS[requestLogicalName] = requestURL;
   },

   sendRequest: function(requestName, options) {
      // Allow for backwards Compatibility
      if ( arguments.length >= 2 )
       if (typeof arguments[1] == 'string')
         options = {parameters: this._createQueryString(arguments, 1)};
      this.sendRequestWithData(requestName, null, options);
   },

   sendRequestWithData: function(requestName, xmlDocument, options) {
      var requestURL = this.requestURLS[requestName];
      if ( requestURL == null )
         return;

      // Allow for backwards Compatibility
      if ( arguments.length >= 3 )
        if (typeof arguments[2] == 'string')
          options.parameters = this._createQueryString(arguments, 2);

      new Ajax.Request(requestURL, this._requestOptions(options,xmlDocument));
   },

   sendRequestAndUpdate: function(requestName,container,options) {
      // Allow for backwards Compatibility
      if ( arguments.length >= 3 )
        if (typeof arguments[2] == 'string')
          options.parameters = this._createQueryString(arguments, 2);

      this.sendRequestWithDataAndUpdate(requestName, null, container, options);
   },

   sendRequestWithDataAndUpdate: function(requestName,xmlDocument,container,options) {
      var requestURL = this.requestURLS[requestName];
      if ( requestURL == null )
         return;

      // Allow for backwards Compatibility
      if ( arguments.length >= 4 )
        if (typeof arguments[3] == 'string')
          options.parameters = this._createQueryString(arguments, 3);

      var updaterOptions = this._requestOptions(options,xmlDocument);

      new Ajax.Updater(container, requestURL, updaterOptions);
   },

   // Private -- not part of intended engine API --------------------------------------------------------------------

   _requestOptions: function(options,xmlDoc) {
      var requestHeaders = ['X-Rico-Version', Rico.Version ];
      var sendMethod = 'post';
      if ( xmlDoc == null )
        if (Rico.prototypeVersion < 1.4)
        requestHeaders.push( 'Content-type', 'text/xml' );
      else
          sendMethod = 'get';
      (!options) ? options = {} : '';

      if (!options._RicoOptionsProcessed){
      // Check and keep any user onComplete functions
        if (options.onComplete)
             options.onRicoComplete = options.onComplete;
        // Fix onComplete
        if (options.overrideOnComplete)
          options.onComplete = options.overrideOnComplete;
        else
          options.onComplete = this._onRequestComplete.bind(this);
        options._RicoOptionsProcessed = true;
      }

     // Set the default options and extend with any user options
     this.options = {
                     requestHeaders: requestHeaders,
                     parameters:     options.parameters,
                     postBody:       xmlDoc,
                     method:         sendMethod,
                     onComplete:     options.onComplete
                    };
     // Set any user options:
     Object.extend(this.options, options);
     return this.options;
   },

   _createQueryString: function( theArgs, offset ) {
      var queryString = ""
      for ( var i = offset ; i < theArgs.length ; i++ ) {
          if ( i != offset )
            queryString += "&";

          var anArg = theArgs[i];

          if ( anArg.name != undefined && anArg.value != undefined ) {
            queryString += anArg.name +  "=" + escape(anArg.value);
          }
          else {
             var ePos  = anArg.indexOf('=');
             var argName  = anArg.substring( 0, ePos );
             var argValue = anArg.substring( ePos + 1 );
             queryString += argName + "=" + escape(argValue);
          }
      }
      return queryString;
   },

   _onRequestComplete : function(request) {
      if(!request)
          return;
      // User can set an onFailure option - which will be called by prototype
      if (request.status != 200)
        return;

      var response = request.responseXML.getElementsByTagName("ajax-response");
      if (response == null || response.length != 1)
         return;
      this._processAjaxResponse( response[0].childNodes );
      
      // Check if user has set a onComplete function
      var onRicoComplete = this.options.onRicoComplete;
      if (onRicoComplete != null)
          onRicoComplete();
   },

   _processAjaxResponse: function( xmlResponseElements ) {
      for ( var i = 0 ; i < xmlResponseElements.length ; i++ ) {
         var responseElement = xmlResponseElements[i];

         // only process nodes of type element.....
         if ( responseElement.nodeType != 1 )
            continue;

         var responseType = responseElement.getAttribute("type");
         var responseId   = responseElement.getAttribute("id");

         if ( responseType == "object" )
            this._processAjaxObjectUpdate( this.ajaxObjects[ responseId ], responseElement );
         else if ( responseType == "element" )
            this._processAjaxElementUpdate( this.ajaxElements[ responseId ], responseElement );
         else
            alert('unrecognized AjaxResponse type : ' + responseType );
      }
   },

   _processAjaxObjectUpdate: function( ajaxObject, responseElement ) {
      ajaxObject.ajaxUpdate( responseElement );
   },

   _processAjaxElementUpdate: function( ajaxElement, responseElement ) {
      ajaxElement.innerHTML = RicoUtil.getContentAsString(responseElement);
   }

}

var ajaxEngine = new Rico.AjaxEngine();


