/**
 * History/Remote - jQuery plugin for enabling history support and bookmarking
 * @requires jQuery v1.0.3
 *
 * http://stilbuero.de/jquery/history/
 *
 * Copyright (c) 2006 Klaus Hartl (stilbuero.de)
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 *
 * Version: 0.2.3
 */

(function($) // block scope
{
  /**
   * Initialize the history manager. Subsequent calls will not result in additional history state change 
   * listeners. Should be called soonest when the DOM is ready, because in IE an iframe needs to be added
   * to the body to enable history support.
   *
   * @example $.ajaxHistory.initialize();
   *
   * @param Function callback A single function that will be executed in case there is no fragment
   *                          identifier in the URL, for example after navigating back to the initial
   *                          state. Use to restore such an initial application state.
   *                          Optional. If specified it will overwrite the default action of 
   *                          emptying all containers that are used to load content into.
   * @type undefined
   *
   * @name $.ajaxHistory.initialize()
   * @cat Plugins/History
   * @author Klaus Hartl/klaus.hartl@stilbuero.de
   */
  $.ajaxHistory = new function() 
  {
    var RESET_EVENT = 'historyReset';

    var _currentHash = location.hash;
    var _intervalId = null;
    var _observeHistory; // define outside if/else required by Opera
    var _enable_observeHistory = true;

    this.cambiaObservador = function(valor) 
    { 
      _enable_observeHistory = valor;
    };
    
    this.estadoObservador = function()
    {
      return _enable_observeHistory;
    }


    this.update = function() { return null; }; // empty function body for graceful degradation

    // create custom event for state reset
    var _defaultReset = function() 
    {
      $('.remote-output1').empty();
      $('.remote-output2').empty();
    };
    $(document).bind(RESET_EVENT, _defaultReset);
        
    // TODO fix for Safari 3
    // if ($.browser.msie)
    // else if hash != _currentHash
    // else check history length


    // INTERNET EXPLORER
    if ($.browser.msie) 
    {
      var _historyIframe, initialized = false; // for IE

      // add hidden iframe
      $(function() 
      {
        _historyIframe = $('<iframe style="display: none;"></iframe>').appendTo(document.body).get(0);
        var iframe = _historyIframe.contentWindow.document;
        // create initial history entry
        iframe.open();
        iframe.close();
        if (_currentHash && _currentHash != '#') 
        {
          iframe.location.hash = _currentHash.replace('#', '');
            
//          if (location.hash) 
//            location.hash = _currentHash;
        }
      });

      this.update = function(hash) 
      {
        var hasAnterior = null;
        _currentHash = hash;
        var iframe = _historyIframe.contentWindow.document;
        iframe.open();
        iframe.close();
        iframe.location.hash = _currentHash ; //.replace('#', '');
        hashAnterior = location.hash;
        if (location.hash)
        {
          location.hash = iframe.location.hash; 
        }
        return hashAnterior;
//          location.hash = _currentHash; //iframe.location.hash; 

      };

      _observeHistory = function() 
      {
        if (_enable_observeHistory)
        {
          var iframe = _historyIframe.contentWindow.document;
          var iframeHash = iframe.location.hash;
          if ((iframeHash != _currentHash) && (iframeHash.substr(1,4) != 'AUTH') )
          {
            //muestralog('JMAN - Comparando -- ' + _currentHash + ' -- ' + iframeHash);
            dondeEstoyHash = _currentHash;
            _currentHash = iframeHash;
            if (iframeHash && iframeHash != '#') 
            {
              // order does matter, set location.hash after triggering the click...
              tipo = 1;
              if (iframeHash.substr(0,2)=="##")
                tipo = 2;
              //muestralog('JMAN - Pulsado -- a[@href$="' + iframeHash + '"] -- ' + Base64.decode(iframeHash.substr(tipo)));

              montarEnlaceConUrlAtras('#' + $('.remote-output' + tipo).get(0).id, iframeHash);
              $('a[@href$="' + iframeHash + '"]').triggerHandler('click');

              location.hash = iframeHash;
            } 
            else if (initialized) 
            {
              //muestralog('JMAN --' + location.hash);
              location.hash = '';
              $(document).trigger(RESET_EVENT);
            }
          }
          initialized = true;
        }
      };

    }
    
    
/*    
    if ($.browser.msie) 
    {
      var _historyIframe, initialized = false; // for IE

      // add hidden iframe
      $(function() 
      {
        _historyIframe = $('<iframe style="display: none;"></iframe>').appendTo(document.body).get(0);
        var iframe = _historyIframe.contentWindow.document;
        // create initial history entry
        iframe.open();
        iframe.close();
        if (_currentHash && _currentHash != '#') 
        {
          if (_currentHash.substr(0,2)=="##")
            iframe.location.hash = _currentHash.replace('##', '');
          else
            iframe.location.hash = _currentHash.replace('#', '');
          muestralog('JUANMA CAPULLETE-------------------->');  
          if (iframe.location.hash) 
            iframe.location.hash = _currentHash;
        }
      });

      this.update = function(hash)
      {
        _currentHash = hash;
        var iframe = _historyIframe.contentWindow.document;
        iframe.open();
        iframe.close();

        muestralog('JMAN IE UPDATE 1 -- iframe.location.hash = ' + Base64.decode(iframe.location.hash.substr(1)) + '');
        if (hash.substr(0,2)=="##")
          iframe.location.hash = hash.replace('##', '');
        else
          iframe.location.hash = hash.replace('#', '');
        muestralog('JMAN IE UPDATE 2 -- iframe.location.hash = ' + Base64.decode(iframe.location.hash.substr(1)) + '');
        if (iframe.location.hash) 
          iframe.location.hash = _currentHash;
        if (location.hash) 
          location.hash = _currentHash;
        muestralog('JMAN IE UPDATE 3 -- location.hash = ' + Base64.decode(iframe.location.hash.substr(1)) + '  ---- _currentHash = ' + Base64.decode(_currentHash.substr(1)));

      };

      _observeHistory = function() 
      {
        if (_enable_observeHistory)
        {
          var iframe = _historyIframe.contentWindow.document;
          var iframeHash = iframe.location.hash;
          if (iframeHash != _currentHash) 
          {
            _currentHash = iframeHash;
            if (iframeHash && iframeHash != '#') 
            {
              // order does matter, set location.hash after triggering the click...
              muestralog('JMAN IE1 -- iframeHash = ' + iframeHash + '');
//              $('a[@href$="' + iframeHash + '"]').click();
//              lanzaUrlConHistory('#' + $('.remote-output1').get(0).id, Base64.decode(iframeHash.substr(1)), 1);
              tipo=1;
              if (iframeHash.substr(0,2)=="##")
                tipo=2;

              lanzaUrlConHistory('#' + $('.remote-output' + tipo).get(0).id, Base64.decode(iframeHash.substr(tipo)), tipo);
              muestralog('JMAN IE2 - ' + '#' + $('.remote-output' + tipo).get(0).id + ' Cambiando el click a ' + Base64.decode(iframeHash.substr(tipo)) );

              iframe.location.hash = iframeHash;
              location.hash = iframeHash;
              muestralog('JMAN IE3 - ' + '#' + $('.remote-output' + tipo).get(0).id + ' Cambiando el click a ' + Base64.decode(iframe.location.hash.substr(tipo)) );
            } 
            else if (initialized) 
            {
              muestralog('JMAN IE -- ' + location.hash);
              location.hash = '';
              $(document).trigger(RESET_EVENT);
            }
          }
          initialized = true;
        }
      };

    }
*/

/*
    // INTERNET EXPLORER
    if ($.browser.msie) 
    {
      var _historyIframe1, _historyIframe2, initialized = false; // for IE

      // add hidden iframe
      $(function() 
      {
        _historyIframe1 = $('<iframe id="iframeIE1" style="display: none;"></iframe>').appendTo(document.body).get(0);
        _historyIframe2 = $('<iframe id="iframeIE2" style="display: none;"></iframe>').appendTo(document.body).get(0);
        var iframe1 = _historyIframe1.contentWindow.document;
        var iframe2 = _historyIframe2.contentWindow.document;
        // create initial history entry
        iframe1.open();
        iframe1.close();
        iframe2.open();
        iframe2.close();
        if (_currentHash && _currentHash != '#') 
        {
          if (_currentHash.substr(0,2)=="##")
            iframe2.location.hash = _currentHash.replace('##', '');
          else
            iframe1.location.hash = _currentHash.replace('#', '');
          if (location.hash) 
            location.hash = _currentHash;
        }
      });

      this.update = function(hash)
      {
        _currentHash = hash;
        var iframe1 = _historyIframe1.contentWindow.document;
        iframe1.open();
        iframe1.close();
        var iframe2 = _historyIframe2.contentWindow.document;
        iframe2.open();
        iframe2.close();

        if (hash.substr(0,2)=="##")
          iframe2.location.hash = hash.replace('##', '');
        else
          iframe1.location.hash = hash.replace('#', '');
        if (location.hash) 
          location.hash = _currentHash;

      };

      _observeHistory = function() 
      {
        var iframe1 = _historyIframe1.contentWindow.document;
        var iframeHash1 = iframe1.location.hash;
        var iframe2 = _historyIframe2.contentWindow.document;
        var iframeHash2 = iframe2.location.hash;
        if (_currentHash.substr(0,2)=="##")
        {
          if (iframeHash2 != _currentHash) 
          {
            _currentHash = iframeHash2;
            if (iframeHash2 && iframeHash2 != '#') 
            {
              // order does matter, set location.hash after triggering the click...
              tipo=2;
              muestralog('JMAN32 - ' + '#' + $('.remote-output' + tipo).get(0).id + ' Cambiando el click a ' + Base64.decode(iframeHash2.substr(tipo)) );
              lanzaUrlConHistory('#' + $('.remote-output' + tipo).get(0).id, Base64.decode(iframeHash2.substr(tipo)), tipo);
              location.hash = iframeHash2;
            } 
            else if (initialized) 
            {
              //muestralog('JMAN --' + location.hash);
              location.hash = '';
              $(document).trigger(RESET_EVENT);
            }
          }
        }
        else
        {
          if (iframeHash1 != _currentHash) 
          {
            _currentHash = iframeHash1;
            if (iframeHash1 && iframeHash1 != '#') 
            {
              // order does matter, set location.hash after triggering the click...
              //muestralog('JMAN -- a[@href$="' + iframeHash + '"]');
              tipo=1;
              muestralog('JMAN31 - ' + '#' + $('.remote-output' + tipo).get(0).id + ' Cambiando el click a ' + Base64.decode(iframeHash1.substr(tipo)) );
              lanzaUrlConHistory('#' + $('.remote-output' + tipo).get(0).id, Base64.decode(iframeHash1.substr(tipo)), tipo);
              location.hash = iframeHash1;
            } 
            else if (initialized) 
            {
              //muestralog('JMAN --' + location.hash);
              location.hash = '';
              $(document).trigger(RESET_EVENT);
            }
          }
        }
        initialized = true;
      };
    }
*/

    // MOZILLA Y OPERA
    else if ($.browser.mozilla || $.browser.opera) 
    {
      this.update = function(hash) 
      {
        //muestralog('JMAN UPDATE 1 -- ' + Base64.decode(hash.substr(1)));
        _currentHash = hash;
        //muestralog('JMAN UPDATE 2 -- _currentHash = ' + Base64.decode(_currentHash.substr(1)));
        if (location.hash) 
         location.hash = _currentHash;
        //muestralog('JMAN UPDATE 3 -- location.hash = ' + Base64.decode(location.hash.substr(1)));
        return null;
      };

      _observeHistory = function()
      {
        //muestralog(_enable_observeHistory + ' -- ' + Base64.decode(_currentHash) + ' -- ' + Base64.decode(location.hash.substr(1)) );
        if (_enable_observeHistory)
        {
          if (location.hash) 
          {
            //muestralog(location.hash + '................' + _currentHash + '........' + location.hash.substr(1,4));
            if ((_currentHash != location.hash) && (location.hash.substr(1,4) != 'AUTH'))
            {
              //muestralog('JMAN1 - Cambiando el click de ' + Base64.decode(_currentHash) + ' a ' + Base64.decode(location.hash.substr(1)) );
              _currentHash = location.hash;

              //muestralog('JMAN2 - Cambiando el click de ' + _currentHash + ' a ' + location.hash.substr(1) );
              tipo=1;
              if (location.hash.substr(0,2)=="##")
                tipo=2;

              if ($('.remote-output' + tipo).length>0)
              {
                lanzaUrlConHistory('#' + $('.remote-output' + tipo).get(0).id, Base64.decode(location.hash.substr(tipo)), tipo);
                //muestralog('JMAN3 - ' + '#' + $('.remote-output' + tipo).get(0).id + ' Cambiando el click a ' + Base64.decode(location.hash.substr(tipo)) );
              }
            }
          } 
          else if (_currentHash)
          {
            muestralog('JMAN - vv' + _currentHash + ' ');
            _currentHash = '';
            $(document).trigger(RESET_EVENT);
            //analizarEnlaces("#" + $('.remote-output').get(0).id);
          }
        }
      };
    } 
    
    // OPERA
    else if ($.browser.safari) 
    {
      var _backStack, _forwardStack, _addHistory; // for Safari

      // etablish back/forward stacks
      $(function() 
      {
        _backStack = [];
        _backStack.length = history.length;
        _forwardStack = [];
      });

      var isFirst = false, initialized = false;
      _addHistory = function(hash) 
      {
        _backStack.push(hash);
        _forwardStack.length = 0; // clear forwardStack (true click occured)
        isFirst = false;
      };

      this.update = function(hash) 
      {
        _currentHash = hash;
        _addHistory(_currentHash);
        return null;
      };

      _observeHistory = function() 
      {
        var historyDelta = history.length - _backStack.length;
        if (historyDelta) // back or forward button has been pushed
        {
          isFirst = false;
          if (historyDelta < 0)  // back button has been pushed
          {
            // move items to forward stack
            for (var i = 0; i < Math.abs(historyDelta); i++) 
              _forwardStack.unshift(_backStack.pop());
          } 
          else  // forward button has been pushed
          {
            // move items to back stack
            for (var i = 0; i < historyDelta; i++) 
              _backStack.push(_forwardStack.shift());
          }
          var cachedHash = _backStack[_backStack.length - 1];
          $('a[@href$="' + cachedHash + '"]').click();
          _currentHash = location.hash;
        } 
        else if (_backStack[_backStack.length - 1] == undefined && !isFirst) 
        {
          // back button has been pushed to beginning and URL already pointed to hash (e.g. a bookmark)
          // document.URL doesn't change in Safari
          if (document.URL.indexOf('#') >= 0) 
          {
            $('a[@href$="' + '#' + document.URL.split('#')[1] + '"]').click();
          } 
          else if (initialized) 
          {
            $(document).trigger(RESET_EVENT);
          }
          isFirst = true;
        }
        initialized = true;
      };
    }


    this.initialize = function(callback) 
    {
      // custom callback to reset app state (no hash in url)
      if (typeof callback == 'function') 
      {
        $(document).unbind(RESET_EVENT, _defaultReset).bind(RESET_EVENT, callback);
      }
      // look for hash in current URL (not Safari)
      if (location.hash && typeof _addHistory == 'undefined') 
      {
        if (location.hash.substr(0,2)=="##")
        {
          location.hash = '';
        }
        else
        {
        
          muestralog('estamos haciendo bookmark con ' + location.hash);
          //Juanma $('.remote-output').load(Base64.decode(location.hash.substr(1)));
          //muestralog("/weblocalizador.aspx?dir="+location.hash.substr(1) + "\n/web/localizador.aspx?dir="+Base64.decode(location.hash.substr(1)));
          $("#zonaLocalizador").load("/web/localizador.aspx?dir="+location.hash.substr(1),
                                     {}, 
                                     function()
                                     {
                                       analizarEnlaces("#zonaLocalizador");
                                     });
          //$('a[@href$="' + location.hash + '"]').trigger('click');
        }
      }
      // start observer
      if (_observeHistory && _intervalId == null) 
      {
        _intervalId = setInterval(_observeHistory, 200); // Safari needs at least 200 ms
      }
    };

  };

  /**
   * Implement Ajax driven links in a completely unobtrusive and accessible manner (also known as "Hijax")
   * with support for the browser's back/forward navigation buttons and bookmarking.
   *
   * The link's href attribute gets altered to a fragment identifier, such as "#remote-1", so that the browser's
   * URL gets updated on each click, whereas the former value of that attribute is used to load content via
   * XmlHttpRequest from and update the specified element. If no target element is found, a new div element will be
   * created and appended to the body to load the content into. The link informs the history manager of the 
   * state change on click and adds an entry to the browser's history.
   *
   * jQuery's Ajax implementation adds a custom request header of the form "X-Requested-With: XmlHttpRequest"
   * to any Ajax request so that the called page can distinguish between a standard and an Ajax (XmlHttpRequest)
   * request.
   *
   * @example $('a.remote').remote( $('#output > div')[0] );
   * @before <a class="remote" href="/path/to/content.html">Update</a>
   * @result <a class="remote" href="#remote-1">Update</a>
   * @desc Alter a link of the class "remote" to an Ajax-enhanced link and let it load content from
   *       "/path/to/content.html" via XmlHttpRequest into an element with the id "output".
   * @example $('a.remote').remote('#output', {hashPrefix: 'chapter'});
   * @before <a class="remote" href="/path/to/content.html">Update</a>
   * @result <a class="remote" href="#chapter-1">Update</a>
   * @desc Alter a link of the class "remote" to an Ajax-enhanced link and let it load content from
   *       "/path/to/content.html" via XmlHttpRequest into an element with the id "output".
   *
   * @param Element elem A DOM element to load content into via XmlHttpRequest.
   * @param Object settings An object literal containing key/value pairs to provide optional settings.
   * @option String hashPrefix A String that is used for constructing the hash the link's href attribute
   *                           gets altered to, such as "#remote-1". Default value: "remote-".
   * @param Function callback A single function that will be executed when the request is complete. 
   * @type jQuery
   *
   * @name remote
   * @cat Plugins/Remote
   * @author Klaus Hartl/klaus.hartl@stilbuero.de
   */
  $.fn.remote = function(output, settings, callback) 
  {
    callback = callback || function() {};
    if (typeof settings == 'function') // shift arguments
    {
      callback = settings;
    }

    settings = $.extend({
                          hashPrefix: 'enlace-diphuelva-'
                        },
                        settings || {}
                       );

    var target = $(output).size() && $(output) || $('<div></div>').appendTo('body');
    target.addClass('remote-output1');

    return this.each(function(i) 
    {
      //var href = this.href, hash = '#' + (this.title && this.title.replace(/\s/g, '_') || settings.hashPrefix + (i + 1)) , a = this;
      var href = this.href, hash = '#' + Base64.encode(this.href) , a = this;
      this.href = hash;
      //muestralog('JuanMa' + this.href);
      $(this).click(function(e) 
      {
        //muestralog('JuanMa A1 ' + this.href);
        // lock target to prevent double loading in Firefox
        if (!target['locked']) 
        {
          //muestralog('JuanMa A2 ' + this.href);
          $.ajaxHistory.cambiaObservador(false);
          // add to history only if true click occured, not a triggered click
          hashAntiguo = location.hash;
          if ((e.clientX) || (this.id=='_enlace_Oculto'))
          {
            //muestralog('JuanMa A3 ' + this.href);
            hashAntiguo = $.ajaxHistory.update(hash);
            //if (hashAntiguo)
            //  muestralog('Click verdadero Pos ' + e.clientX + ' Tipo ' + e.type + ' ----' + Base64.decode(hash) + '----' + $.ajaxHistory.estadoObservador() + '---' + Base64.decode(hashAntiguo.replace("#","")));
          }

          //muestralog('Pos X' + e.clientX + 'Pos Y' + e.clientY + ' Tipo ' + e.type + ' ----' + Base64.decode(hash));
          target.fadeOut("fast").load(href,
                                      {},
                                      function()
                                      {
                                        $("#zonaLocalizador").load( "/web/localizador.aspx?dir="+Base64.encode(href),
                                                                    {}, 
                                                                    function()
                                                                    {
                                                                      analizarEnlaces("#zonaLocalizador");
                                                                    });
                                        target['locked'] = null;
                                        callback.apply(a);
                                        analizarEnlaces('#' + $(output).get(0).id);
                                        target.fadeIn("fast");
                                        setTimeout("$.ajaxHistory.cambiaObservador(true)", 1000);
                                      });
        }
      });
    });
  };




  /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
   *                                                                                       *
   *                                                                                       *
   *                                                                                       *
   * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  $.fn.remote2 = function(output, settings, callback) 
  {
    callback = callback || function() {};
    if (typeof settings == 'function') // shift arguments
    {
      callback = settings;
    }

    settings = $.extend({
                          hashPrefix: 'enlace-diphuelva-'
                        },
                        settings || {}
                       );


    var target = $(output).size() && $(output) || $('<div></div>').appendTo('body');
    target.addClass('remote-output2');

    return this.each(function(i) 
    {
      //var href = this.href, hash = '#' + (this.title && this.title.replace(/\s/g, '_') || settings.hashPrefix + (i + 1)) , a = this;
      var href = this.href, hash = '##' + Base64.encode(this.href) , a = this;
      this.href = hash;
      $(this).click(function(e) 
      {
        muestralog('JuanMa BB ' + Base64.decode(this.href.substr(2)));
        // lock target to prevent double loading in Firefox
        if (!target['locked']) 
        {
          $.ajaxHistory.cambiaObservador(false);
          // add to history only if true click occured, not a triggered click

          //muestralog('JuanMa BB 1 ' + Base64.decode(location.hash.replace("##","").replace("#","")));
          hashAntiguo =location.hash;
          if ((e.clientX) || (this.id=='_enlace_Oculto'))
          {
            //muestralog('JuanMa BB 2 ' + href);
            //muestralog('Click verdadero Pos ' + e.clientX + ' Tipo ' + e.type + ' ----' + Base64.decode(hash) + '----' + $.ajaxHistory.estadoObservador());
            hashAntiguo = $.ajaxHistory.update(hash);
            //if (hashAntiguo)
            //  muestralog('Click verdadero Pos ' + e.clientX + ' Tipo ' + e.type + ' ----' + Base64.decode(hash) + '----' + $.ajaxHistory.estadoObservador() + '---' + Base64.decode(hashAntiguo.replace("#","")));
          }

          muestralog('JuanMa BB 3 ' + href);
          //muestralog('Pos X' + e.clientX + 'Pos Y' + e.clientY + ' Tipo ' + e.type + ' ----' + Base64.decode(hash));
          target.fadeOut("fast").load(href,
                                      {},
                                      function()
                                      {
//                                        $("#zonaLocalizador").load( "/web/localizador.aspx?dir="+Base64.encode(href),
//                                                                    {}, 
//                                                                    function()
//                                                                    {
//                                                                      analizarEnlaces("#zonaLocalizador");
//                                                                    });
                                        target['locked'] = null;
                                        callback.apply(a);
                                        analizarEnlaces2('#' + $(output).get(0).id);
                                        target.fadeIn("fast");
                                        setTimeout("$.ajaxHistory.cambiaObservador(true)", 1000);
                                      });
        }
      });
    });
  };

  /**
   * Provides the ability to use the back/forward navigation buttons in a DHTML application.
   * A change of the application state is reflected by a change of the URL fragment identifier.
   *
   * The link's href attribute needs to point to a fragment identifier within the same resource,
   * although that fragment id does not need to exist. On click the link changes the URL fragment
   * identifier, informs the history manager of the state change and adds an entry to the browser's
   * history.
   *
   * @param Function callback A single function that will be executed as the click handler of the 
   *                          matched element. It will be executed on click (adding an entry to 
   *                          the history) as well as in case the history manager needs to trigger 
   *                          it depending on the value of the URL fragment identifier, e.g. if its 
   *                          current value matches the href attribute of the matched element.
   *                           
   * @type jQuery
   *
   * @name history
   * @cat Plugins/History
   * @author Klaus Hartl/klaus.hartl@stilbuero.de
   */
  $.fn.history = function(callback) 
  {
    return this.click(function(e) 
    {
      muestralog(' ----------- ');
      // add to history only if true click occured, not a triggered click
      if (e.clientX) 
      {
        muestralog('Botón Historia a ' + Base64.decode(this.hash.substr(1)));
        $.ajaxHistory.update(this.hash);
      }
      typeof callback == 'function' && callback();
    });
  };

})(jQuery);

