/* TEUSA Javascript
 * by illarra design & internet
 * 2009 - 2010
 */
// Create base namespace
teusa = {};

/**
 * Utils
 * Utility method for working easier in the project.
 */
teusa.utils = (function () {
  // Public Methods
  return {
    isObject: function (o) 
    {
      return (o && (typeof o === 'object' || this.isFunction(o))) || false;
    },    
    isString: function (o)
    {
      return typeof o === 'string';
    },    
    isUndefined: function (o)
    {
      return typeof o === 'undefined';
    },      
    listObject: function (o)
    {
      var result = '';
    
      for (property in o) {
        result += property + 
                  ((o.hasOwnProperty(property)) ? ' (true)' : '(false)') +
                  ': ' + o[property] + '\n';
      }
      
      return result;
    },    
    map: function (fn, a) {
      for (i = 0; i < a.length; i++) {
          a[i] = fn(a[i]);
      }
    },    
    namespace: function (ns) {
      var nsParts = ns.split("."),
          root    = window,
          i;

      for (i = 0; i < nsParts.length; i++) {
        if (typeof root[nsParts[i]] == "undefined") {
          root[nsParts[i]] = new Object();
        }
          
        root = root[nsParts[i]];
      }        
    },
    object: function (o)
    {
      function F(){};
      F.prototype = o;
      return new F();
    },    
    reduce: function (fn, a, init) {
      var s = init;
      
      for (i = 0; i < a.length; i++) {
          s = fn( s, a[i] );
      }
      
      return s;
    }    
  };
})();

/**
 * Info
 * Get basic information: base path, language, ... 
 */
teusa.info = (function ()
{
  var base = '', 
      lang = '';
  
  return {
    getBasePath: function ()
    {
      return base;
    },
    getLanguage: function ()
    {
      return lang;
    },
    setBasePath: function (_base) 
    {
      base = _base;
    },
    setLanguage: function (_lang)
    {
      lang = _lang;
    }
  }
})();

/**
 * AJAX
 */
teusa.ajax = function(ops) {
  // Bariableak definitu
  var cacheData;
  
  // Defektuzko baloreak definitu
  ops.url        = ops.url        || '';
  ops.dataType   = ops.dataType   || 'json';
  ops.beforeSend = ops.beforeSend || function () {};
  ops.complete   = ops.complete   || function () {};
  ops.error      = ops.error      || function () {};
  ops.success    = ops.success    || function () {};
  
  // URL-ea definitu gabe badago ez du ezer egingo funtzioak
  if (ops.url == '') {
    return false;
  }
  
  // Katxean begiratu ea emandako eskaerak existitze duen
  if ($.jCache.hasItem(ops.url)) {
    // Ala bada, katxea kargatu eta opzioetatik pasatako 'success' handler-a deitu
    cacheData = $.jCache.getItem(ops.url);
    ops.success(cacheData.data, cacheData.textStatus);
  } else {
    $.ajax({
      url: ops.url,
      dataType: ops.dataType,
      beforeSend: function (XMLHttpRequest) {
        // Opzioetatik pasatako 'beforeSend' handler-ari deitu
        ops.beforeSend(XMLHttpRequest);
      },
      complete: function (XMLHttpRequest, textStatus) {
        // Opzioetatik pasatako 'complete' handler-ari deitu
        ops.complete(XMLHttpRequest, textStatus);
      },
      error: function (XMLHttpRequest, textStatus, errorThrown) {      
        // Opzioetatik pasatako 'error' handler-ari deitu
        ops.error(XMLHttpRequest, textStatus, errorThrown);
      },
      success: function (data, textStatus) {      
        // Opzioetatik pasatako 'success' handler-ari deitu
        $.jCache.setItem(ops.url, {'data':data, 'textStatus':textStatus});
        ops.success(data, textStatus);      
      }
    });
  }
}

/**
 * Simple Javascript Templating
 * John Resig - http://ejohn.org/ - MIT Licensed
 * http://ejohn.org/blog/javascript-micro-templating/
 */
teusa.template = (function () {
  var cache = {};
  
  function tmpl(str, data) {
    // Figure out if we're getting a template, or if we need to
    // load the template - and be sure to cache the result.
    var fn = !/\W/.test(str) ?
      cache[str] = cache[str] || tmpl(document.getElementById(str).innerHTML) :
      
    // Generate a reusable function that will serve as a template
    // generator (and which will be cached).
    new Function("obj",
    "var p=[],print=function(){p.push.apply(p,arguments);};" +
    
    // Introduce the data as local variables using with(){}
    "with(obj){p.push('" +
    
    // Convert the template into pure JavaScript
    // Oharra: defektuzko <% => <# bihurtuta
    str
      .replace(/[\r\t\n]/g, " ")
      .split("<#").join("\t")
      .replace(/((^|#>)[^\t]*)'/g, "$1\r")
      .replace(/\t=(.*?)#>/g, "',$1,'")
      .split("\t").join("');")
      .split("#>").join("p.push('")
      .split("\r").join("\\'")
      + "');}return p.join('');");
    
    // Provide some basic currying to the user
    return data ? fn( data ) : fn;
  };
  
  return tmpl;
})();

/**
 * Filter Class
 */
teusa.utils.namespace('teusa.Filter');

teusa.Filter = (function ()
{
  var Filter = (function ()
  {
    var filter = {},
        subsetList = [],
        subsetDict = {},
        action, subset;
    
    /**
     * Get Subset
     * Given an array of strings it returns an object with the matched properties
     * that are found in the input array.
     */
    function getSubset() 
    {
      var result = {},
          p;
      
      for (p in subsetList) {
        if (!teusa.utils.isUndefined(filter[subsetList[p]])) {
          result[subsetList[p]] = filter[subsetList[p]];
        }
      }
      
      return result;
    }
    
    return {
      _init: function (ops)
      {
        var p;
      
        action = ops.action || '';
        subset = ops.subset || {};
        
        for (p in subset) {
          subsetDict[subset[p]] = p;
          subsetList.push(p);
        }
      },
      getApiUrl: function ()
      {
        var url       = teusa.info.getBasePath() + '/api/' + action + '.json', 
            urlParams = [],
            list      = getSubset(),
            p;
        
        for (p in list) {
          urlParams.push(p + '=' + list[p]);
        }        
        
        if (urlParams.length > 0) {
          url += '?' + urlParams.join('&');
        }
        
        return url;
      },
      getFilter: function ()
      {
        return filter;
      },
      getHash: function ()
      {
        var list    = getSubset(),
            hash    = [],
            p;
            
        for (p in list) {
          hash.push(subset[p] + '/' + list[p]);
        }
            
        return hash.join('/');
      },
      setFilter: function (f)
      {
        var i, name, result = {};
        
        if (teusa.utils.isString(f)) {
          // Trim "/" from the input string & split using "/"
          f = f.replace(/^(\/)*/, '').replace(/(\/)*$/, '').split('/');
          
          for (i = 0; i < f.length; i += 2) {
            // Check if the element is a traduction of a subset element
            if (!teusa.utils.isUndefined(subsetDict[f[i]])) {
              name = subsetDict[f[i]];
            } else {
              name = f[i];
            }

            result[name] = f[i+1];
          }
        } else if (teusa.utils.isObject(f)) {
          result = f;
        }
        
        filter = result;
      }
    };
  })();
  
  return function (ops)
  {
    var instance = teusa.utils.object(Filter);
    instance._init(ops);
    return instance;
  };
})();

/**
 * Obra Archive
 */
teusa.utils.namespace('teusa.obra.archive');

teusa.obra.archive = (function ()
{
  var filterParams = {},
      filter;
  
  /**
   * Initialize Form
   * Initializes the form on the first load. The #hash options are reflected
   * into the form.
   */
  function initForm()
  {
    var updateForm, list, p;
    
    // Update input select
    function updateSelect(id)
    {
      return function (value)
      {
        $(id).val(value); 
      };
    }
    
    // Update checkbox list
    function updateCheckboxes(id)
    {
      return function (value)
      {
        var labels = value.split('+'),
            i;
        
        for (i = 0; i < labels.length; i++) {
          $(id + '_' + labels[i]).attr('checked', true);
        }
      };
    }

    // Create the methods for handling the form update
    updateForm = {
      'page':      function(){},
      //'client':    updateSelect('#obra_filters_client_id'),
      'status':    updateSelect('#obra_filters_status'),
      'provincia': updateSelect('#obra_filters_provincia_id'),
      //'tecnica':   updateCheckboxes('#obra_filters_tecnicas_list'),
      'tipologia': updateCheckboxes('#obra_filters_tipologias_list')
      //'material':  updateCheckboxes('#obra_filters_materiales_list')
    };
    
    // Generate filter options
    filter.setFilter(SWFAddress.getPath());
    list = filter.getFilter();

    // Loop through each filter option
    for (p in list) {
      if (!teusa.utils.isUndefined(updateForm[p])) {
        updateForm[p](list[p]);
      }
    }
  }
  
  /**
   * Handle Form Select
   * Handles filter forms select elements, its a helper function.
   */
  function handleFormSelect(id)
  {
    return function ()
    {
      var value = $(id).val();
      
      if (value != '') { 
        return value; 
      } else { 
        return null;
      }      
    };
  }
  
  /**
   * Hanndle Form Checkboxes
   * Handles filter forms checkbox elements, its a helper function.
   */
  function handleFormCheckboxes(id)
  {
    return function ()
    {
      var list = $("input[id^=" + id + "]:checkbox:checked"),
          labels = [];

      if (list.length == 0) {
        return null;
      } else {
        list.each(function () {
          labels.push(this.value);
        });
      
        return labels.join('+');
      }      
    };
  }
  
  /**
   * Filter Parameters
   * Object containing the necesary methods to get filter form parameters.
   */
  filterParams = {
    //'client':    handleFormSelect('#obra_filters_client_id'),
    'status':    handleFormSelect('#obra_filters_status'),
    'provincia': handleFormSelect('#obra_filters_provincia_id'),
    //'tecnica':   handleFormCheckboxes('obra_filters_tecnicas_list'),
    'tipologia': handleFormCheckboxes('obra_filters_tipologias_list')
    //'material':  handleFormCheckboxes('obra_filters_materiales_list')
  }
  
  /**
   * Handle Filter
   * Handles filter form click event.
   */
  function handleFilter(e)
  {
    var formFilter = {},
        p, value; 
    
    if (e) {
      e.preventDefault();
    }
    
    // Reset Flying Div
    $(window).scrollTop(0);
    $('#flyingDiv').css('marginTop', 0);
    
    // Formulariyotik datuak jaso eta filtro objetua sortu
    for (p in filterParams) {
      value = filterParams[p]();
      
      if (value !== null) {
        formFilter[p] = value;
      }
    }
    
    // Filtrua definitu eta #hash-a aldatu
    filter.setFilter(formFilter);
    SWFAddress.setValue(filter.getHash());
  }
  
  /**
   * Handle Hash Change
   * Every time the #hash is changed this function is called. 
   */
  function handleHashChange(o)
  {
    var url;
    
    // Save the filter data
    filter.setFilter(o.path);
    
    // Get the request URL
    url = filter.getApiUrl();
    
    // Show loading view
    $('#obra_list').hide();
    $('#obra_list_loading').show();
    
    // Check if cache exists
    if ($.jCache.hasItem(url)) {
      // Update the list view
      $('#obra_list').html($.jCache.getItem(url));
      
      // Hide loading view
      $('#obra_list_loading').hide();
      $('#obra_list').show();
    } else {      
      teusa.ajax({
        'url': url,
        'complete': function (XMLHttpRequest, textStatus)
        {
          // Hide loading view
          $('#obra_list_loading').hide();
          $('#obra_list').show();
        },
        'error': function (XMLHttpRequest, textStatus, errorThrown)
        {
          // Show error view
          $('#obra_list').html(teusa.template('obra_tpl_error',{}));        
        },
        'success': function (data, textStatus) 
        {
          var view;
          
          // Generate the view
          view = teusa.template('obra_tpl', data);
          
          // Update the view
          $('#obra_list').html(view);
          
          // Save data into the cache
          $.jCache.setItem(url, view);
        }
      });  
    }
  }
  
  return {
    /**
     * Initialize
     * Initializes the obras archive page.
     */
    init: function () 
    {
      // Init filter
      filter = teusa.Filter({
        action: 'obra',
        subset: {
          page:      'pagina',
          status:    'situacion',
          provincia: 'provincia',
          tipologia: 'tipologia'
        }
      });
    
      // Filters Scroll
      $(window).scroll((function () {
        var pos = $('#flyingDiv').offset().top, // Initial position
            height = $('#flyingDiv').height(),  // Div height
            footer = $('#ft');                  // Footer element
        
        return function (e) {
          var scroll = $(window).scrollTop(),  // Scroll from top
              footerPos = footer.offset().top, // Footer position
              upperPos = footerPos - height,   // Upper limit position
              margin, safetyMargin = 20;       // New margin
          
          // Calculate the top margin
          if ((scroll > pos) && (scroll < upperPos)) {
            margin = (scroll - pos + safetyMargin) + 'px';
          } else if (scroll <= pos) {
            margin = safetyMargin - 20 + 'px';
          } else {
            margin = (upperPos - pos + safetyMargin) + 'px';
          }          
          
          // Animate the div
          $('#flyingDiv').stop().animate({
            marginTop: margin
          }, 300, 'swing');          
        }
      })());
      
      // Click action for the paginator links
      $('#obras_paginator a').live('click', function () {
        var page = this.href.split('#')[1];
        teusa.obra.archive.page(page);
        return false;
      });
      
      // Set the onchange event listener
      SWFAddress.addEventListener(SWFAddressEvent.CHANGE, handleHashChange);
      
      // Handle Filter Form (we use a timeout for the stupid IE7, otherwise it won't register the event)
      setTimeout(function(){
        $('#FiltrarObras').click(function(e) {handleFilter(e);});
      }, 500);
      
      // Init Form
      initForm();
    },
    /**
     * Page
     * Changes the actual page.
     */
    page: function (number)
    {
      var newFilter = filter.getFilter();
      
      if (number == 1) {
        if (!teusa.utils.isUndefined(newFilter.page)) {
          delete newFilter.page;
        }
      } else {
        newFilter.page = number;
      }
      
      filter.setFilter(newFilter);
      SWFAddress.setValue(filter.getHash());
    }
  }
})()

/**
 * Post Archive
 */
teusa.utils.namespace('teusa.post.archive');

teusa.post.archive = (function()
{
  var filter;
  
  /**
   * Handle Hash Change
   * Every time the #hash is changed this function is called. 
   */
  function handleHashChange(o)
  {
    var url;
    
    // Save the filter data
    filter.setFilter(o.path);
    
    // Get the request URL
    url = filter.getApiUrl();
    
    // Show loading icon
    // TODO: SHOW LOADING ICON !!!!!!!!!
    
    // Check if cache exists
    if ($.jCache.hasItem(url)) {
      // Update the list view
      $('#post_list').html($.jCache.getItem(url));
      // Hide loading icon
      // TODO: HIDE LOADING ICON !!!!!!!!!!!!!
    } else {      
      teusa.ajax({
        'url': url,
        'complete': function (XMLHttpRequest, textStatus)
        {
          // Hide loading icon
          // TODO: HIDE LOADING ICON !!!!!!!!!!!!!
        },
        'error': function (XMLHttpRequest, textStatus, errorThrown)
        {
          // Show error view
          $('#post_list').html(teusa.template('post_tpl_error', {}));        
        },
        'success': function (data, textStatus) 
        {
          var view;
          
          // Generate the view
          view = teusa.template('post_tpl', data);
          
          // Update the view
          $('#post_list').html(view);
          
          // Save data into the cache
          $.jCache.setItem(url, view);
        }
      });  
    }
  }
  
  return {
    init: function () 
    {
      // Init Filter
      filter = teusa.Filter({action: 'post', subset: {page: 'pagina'}});
    
      // Click action for the paginator links
      $('#posts_paginator a').live('click', function () {
        var page = this.href.split('#')[1];
        teusa.post.archive.page(page);
        return false;
      });
      
      // Set the onchange event listener
      SWFAddress.addEventListener(SWFAddressEvent.CHANGE, handleHashChange);      
    },
    page: function (number)
    {
      var newFilter = filter.getFilter();
      
      if (number == 1) {
        if (!teusa.utils.isUndefined(newFilter.page)) {
          delete newFilter.page;
        }
      } else {
        newFilter.page = number;
      }
      
      filter.setFilter(newFilter);
      SWFAddress.setValue(filter.getHash());
    }
  };
})();

/**
 * Initializer
 */
$(document).ready(function () {
  /* Path regex, will use this as basis for the initializer. For example,
   * for 'xxx/eu/page/about#/b' the resulting captured groups would be:
   * 1 = 'eu'
   * 2 = 'page/about'
   */
  var path_regex = new RegExp( /^(.*?)\/(eu|es|fr)(?:\/)?([^#]*).*/ ),
      m          = path_regex.exec( window.location.toString().replace( /#$/, '' ) ), // rtrim #
      base, lang, path;
  
  base = m[1];
  lang = m[2];
  path = m[3];  
  
  teusa.info.setBasePath(base);
  teusa.info.setLanguage(lang);
  
  switch (true) {
  case "empresa" == path:
    // Map
    var map = document.getElementById('map_canvas'),
	    lat = $('#latitude').attr('title'),
	    lng = $('#longitude').attr('title'),
        markerTitle = '';
  
    // Define the LatLng point
    mapLatLng = new google.maps.LatLng(lat, lng);
    
    // We create the map
    oMap = new google.maps.Map(map, {
      'zoom': 11,
      'center': mapLatLng,
      'mapTypeId': google.maps.MapTypeId.ROADMAP,
      'mapTypeControlOptions': {style: google.maps.MapTypeControlStyle.DROPDOWN_MENU},
      'scrollwheel': false // We disable scroll wheel zoom, as I found it annoying :)
    });
    
    // And set the marker
    oMarker = new google.maps.Marker({
      'position': mapLatLng, 
      'map': oMap,
      'title': markerTitle,
      'icon': '/css/images/marker-blue.png'
    });
  break;
  // Obra Archive
  case "obras" == path:
    teusa.obra.archive.init();
  break;
  case "noticias" == path:
    teusa.post.archive.init();
  break;
  // Obra View
  case path.match(/obra\/[0-9]+\/.+/) != null:
    // Lightbox gallery
    $('#gallery a').lightBox({
      imageLoading:  '/css/images/lightbox-ico-loading.gif',
      imageBtnClose: '/css/images/lightbox-btn-close.gif',
      imageBtnPrev:  '/css/images/lightbox-btn-prev.gif',
      imageBtnNext:  '/css/images/lightbox-btn-next.gif',
      txtImage:      '',
      txtOf:         '/'
    });  
  break;
  }
});
