/*
  Extension for the autocompleter
*/
var Mdarad = {}
Mdarad.Autocompleter = Class.create(Ajax.Autocompleter, {
  initialize: function(element, idElement, update, url, options) {
    this.baseInitialize(element, update, options);
    this.options.asynchronous  = true;
    this.options.onComplete    = this.onComplete.bind(this);
    this.options.defaultParams = this.options.parameters || null;
    this.url                   = url;
    var context = this;
    this.options.onHide = function(element, update){ 
        if(context.options.onValidation) {
            context.options.onValidation.call();
        }
        new Effect.Fade(update,{duration:0.15}) }

    if(this.options.propertyName == null) this.options.propertyName = "id";
    if(this.options.propertyType == null) this.options.propertyType = "string";
    if(this.options.operator == null) this.options.operator = "START_WITH";
    
    this.options.method = "post";
    this.options.requestHeaders = ['cache-control','no-cache','pragma','no-cache', 'content-type', 'application/xml'];
    

    if (!this.options["classType"]) {
        throw "EXCEPTION : The class must be specified for XML parsing.";
    }
        
    this.options.classType = this.options.classType;
    this.options.afterUpdateElement = this.afterUpdateElement.bind(this);
    this.idElement = $(idElement);
    
    MdaradUtils.addEvent($(element), "keydown", this.updateIdElement.bind(this, $(element), $(idElement)));
  },

  updateIdElement: function(element, idElement, event) {
        if(event.keyCode != 9 && event.keyCode != 13) {
            idElement.value = "";
        }
  },
  
  onComplete: function(transport) {
    if (transport.status != 200) {
        alert('ERROR RETRIEVING XML DATA : Status ' + transport.status);         
    }
      
    var xml = transport.responseXML.documentElement;
    var json = MdaradUtils.xml2json(xml, '').evalJSON();
    var results = new Array();
    if (json.SearchResults != null) {
        if (json.SearchResults.results != null) {
            results =  MdaradUtils.jsonElementArray(json.SearchResults.results[this.options["classType"]]);
        }
    }
    
    var list = "<ul>";
    for (var i = 0; i < results.length; i++) {
        list += this.getListElement(results[i]);
    }
    
    list += "</ul>";    
    
    this.updateChoices(list);
  },
  
  getListElement: function(object) {
    return "<li id=\"" + object["@refid"] + "\">" + object["@label"] + "</li>";
  },
  
  getUpdatedChoices: function($super) {
    try {
        this.options.postBody = this.getXMLPostDoc();
    } catch (e) {
        MdaradUtils.logException(e);
    }
    $super();
  },


  getXMLPostDoc : function() {
    var xmlDoc = MdaradUtils.createXMLDocument();
    
    var searchParametersNode = 
        Mdarad.Builder.node(xmlDoc, "SearchParameters", [
            Mdarad.Builder.node(xmlDoc, "firstCriterion", [
                Mdarad.Builder.node(xmlDoc, "OperationsCriterion", [
                    Mdarad.Builder.node(xmlDoc, "operations", [
                        Mdarad.Builder.node(xmlDoc, "Operation", {propertyType: this.options.propertyType }, [
                            Mdarad.Builder.node(xmlDoc, "operator", [this.options.operator]),
                            Mdarad.Builder.node(xmlDoc, "value", [this.getToken() ]),
                            Mdarad.Builder.node(xmlDoc, "property", [
                                Mdarad.Builder.node(xmlDoc, "Property", [                            
                                    Mdarad.Builder.node(xmlDoc, "name", [this.options.propertyName])
                                ])
                            ])
                        ])
                    ])
                ])
            ])
        ]);
    xmlDoc.appendChild(searchParametersNode);
    return xmlDoc;
  },
  
  
  afterUpdateElement: function(element, selectedElement) {
    this.idElement.value = selectedElement.id;    
  }
});           










/*
  Extension for the Builder to which we can pass the "creative" document.  This
  is necessary because the XML document needs to create its own elements in order to 
  append them in IE.
  
  Modifications: - see comments below
                 - added doc as an argument 
                 - consequence: for arguments[x], x was incremented by one
*/
Mdarad.Builder = Class.create();
Object.extend(Object.extend(Mdarad.Builder, Builder), {


  // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken,
  //       due to a Firefox bug
  node: function(doc, elementName) {
    elementName = elementName.toUpperCase();
    
    // try innerHTML approach
    var parentTag = this.NODEMAP[elementName] || 'div';
    var parentElement = doc.createElement(parentTag);
    try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
      parentElement.innerHTML = "<" + elementName + "></" + elementName + ">";
    } catch(e) {}
    var element = parentElement.firstChild || null;
      
    // see if browser added wrapping tags
    if(element && (element.tagName.toUpperCase() != elementName))
      element = element.getElementsByTagName(elementName)[0];
    
    // fallback to createElement approach
    if(!element) element = doc.createElement(elementName);
    
    // abort if nothing could be created
    if(!element) return;

    // attributes (or text)
    if(arguments[2])
      if(this._isStringOrNumber(arguments[2]) ||
        (arguments[2] instanceof Array)) {
          this._children(doc, element, arguments[2]);
      } else {
          var attrs = this._attributes(arguments[2]);
          if(attrs.length) {
            try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
              parentElement.innerHTML = "<" +elementName + " " +
                attrs + "></" + elementName + ">";
            } catch(e) {}
            element = parentElement.firstChild || null;
            // workaround firefox 1.0.X bug
            if(!element) {
              element = doc.createElement(elementName);
              //MDARAD: Start Modification
              for(attr in arguments[2]) {
                //element[attr == 'class' ? 'className' : attr] = arguments[2][attr]);
                element.setAttribute(attr == 'class' ? 'className' : attr, arguments[2][attr]);
              }
              //MDARAD: End Modification
            }
            if(element.tagName.toUpperCase() != elementName)
              element = parentElement.getElementsByTagName(elementName)[0];
            }
        } 

    // text, or array of children
    if(arguments[3])
      this._children(doc, element, arguments[3]);

     return element;
  },
  _text: function(doc, text) {
     return doc.createTextNode(text);
  },

  _children: function(doc, element, children) {
    if(typeof children=='object') { // array can hold nodes and text
      children.flatten().each( function(e) {
        if(typeof e=='object')
          element.appendChild(e)
        else
          if(Builder._isStringOrNumber(e))
            element.appendChild(Mdarad.Builder._text(doc, e));
      });
    } else
      if(Builder._isStringOrNumber(children)) 
         element.appendChild(Mdarad.Builder._text(doc, children));
  },
  build: function(doc, html) {
    var element = this.node(doc, 'div');
    $(element).update(html.strip());
    return element.down();
  },
  dump: function(doc, scope) { 
    if(typeof scope != 'object' && typeof scope != 'function') scope = window; //global scope 
  
    var tags = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY " +
      "BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET " +
      "FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX "+
      "KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P "+
      "PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD "+
      "TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/);
  
    tags.each( function(tag){ 
      scope[tag] = function() { 
        return Builder.node.apply(Builder, [tag].concat($A(arguments)));  
      } 
    });
  }
  
});


Effect.SlideRight = function(element) {
  element = $(element);
  Element.cleanWhitespace(element);
  // SlideDown need to have the content of the element wrapped in a container element with fixed height!
  var oldInnerRight = Element.getStyle(element.firstChild, 'right');
  var elementDimensions = Element.getDimensions(element);
  return new Effect.Scale(element, 100, Object.extend({ 
    scaleContent: false, 
    scaleY: false, 
    scaleFrom: 0,
    scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
    restoreAfterFinish: true,
    afterSetup: function(effect) { with(Element) {
      makePositioned(effect.element);
      makePositioned(effect.element.firstChild);
      if(window.opera) setStyle(effect.element, {top: ''});
      makeClipping(effect.element);
      setStyle(effect.element, {width: '0px'});
      show(element); }},
    afterUpdateInternal: function(effect) { with(Element) {
      setStyle(effect.element.firstChild, {right:
        (effect.dims[0] - effect.element.clientWidth) + 'px' }); }},
    afterFinishInternal: function(effect) { with(Element) {
      undoClipping(effect.element); 
      undoPositioned(effect.element.firstChild);
      undoPositioned(effect.element);
      setStyle(effect.element.firstChild, {right: oldInnerRight}); }}
    }, arguments[1] || {})
  );
}

Effect.SlideLeft = function(element) {
  element = $(element);
  Element.cleanWhitespace(element);
  var oldInnerRight = Element.getStyle(element.firstChild, 'right');
  return new Effect.Scale(element, 0, 
   Object.extend({ scaleContent: false, 
    scaleY: false, 
    scaleMode: 'box',
    scaleFrom: 100,
    restoreAfterFinish: true,
    beforeStartInternal: function(effect) { with(Element) {
      makePositioned(effect.element);
      makePositioned(effect.element.firstChild);
      if(window.opera) setStyle(effect.element, {top: ''});
      makeClipping(effect.element);
      show(element); }},  
    afterUpdateInternal: function(effect) { with(Element) {
      setStyle(effect.element.firstChild, {right:
        (effect.dims[0] - effect.element.clientWidth) + 'px' }); }},
    afterFinishInternal: function(effect) { with(Element) {
        hide(effect.element);	        
        undoClipping(effect.element);
        
        undoPositioned(effect.element.firstChild);
        undoPositioned(effect.element);
        setStyle(effect.element.firstChild, {right: oldInnerRight}); }}
   }, arguments[1] || {})
  );
}
