/**
 * @company: DP2I
 * @author: Nicolas Pelletier
 */

if (!Array.prototype.map) {
  Array.prototype.map = function(fun /*, thisp*/) {
    var len = this.length;
    if (typeof fun != "function")
      throw new TypeError();

    var res = new Array(len);
    var thisp = arguments[1];
    for (var i = 0; i < len; i++) {
      if (i in this)
        res[i] = fun.call(thisp, this[i], i, this);
    }

    return res;
  };
}

if (!Array.prototype.filter) {
  Array.prototype.filter = function(fun /*, thisp*/)
  {
    var len = this.length;
    if (typeof fun != "function")
      throw new TypeError();

    var res = new Array();
    var thisp = arguments[1];
    for (var i = 0; i < len; i++) {
      if (i in this) {
        var val = this[i]; // in case fun mutates this
        if (fun.call(thisp, val, i, this))
          res.push(val);
      }
    }

    return res;
  };
};

if (!Array.prototype.findIndex) {
  Array.prototype.findIndex = function (fn) {
    for (var i = 0, l = this.length; i < l; i++)
      if (fn.call(this, this[i], i)) return i;
    return -1;
  };
}

if (!Array.prototype.squash) {
  Array.prototype.squash = function (reference) {
    var result = [], flag = false;
    for (var i = 0, l = this.length; i < l; i++)
      if (this[i] == reference) {
        if (!flag) {
          flag = true;
          result.push(this[i]);
        }
      } else {
        if (flag) flag = false;
        result.push(this[i]);
      }
    return result;
  };
}

if (!Array.prototype.iter) {
  Array.prototype.iter = function (fn) {
    for (var i = 0, l = this.length; i < l; i++)
      fn.call(this, this[i], i);
    return this;
  };
}

if (!Array.prototype.fold) {
  Array.prototype.fold = function (fn, accu) {
    for (var i = 0, l = this.length; i < l; i++)
      accu = fn.call(this, this[i], accu, i);
    return accu;
  };
}

if (!String.prototype.trim) {
  String.prototype.trim = function () {
    return (this || '').replace(/^\s+/, '').replace(/\s+$/, '');
  };
}


/*********************************************************************/

var getCookie = function (name) {
  var cookies = document.cookie.split(";");
  for (var i = 0; i < cookies.length; i++) {
    var cookie = cookies[i].split('=');
    if (name == unescape(cookie[0].replace(/^\s+|\s+$/g, '')))
      return unescape(cookie[1]);
  }
};

var setCookie = function (name, value, expires, path, domain, secure) {
  var exdate = new Date();
  if (expires) exdate.setHours(exdate.getHours() + (expires || 0));
  document.cookie = escape(name) + '=' + escape(value) +
    (expires ? ';expires=' + exdate.toUTCString() : '') +
    (path    ? ';path=' + path : ';path=/') +
    (domain  ? ';domain=' + domain : '') +
    (secure  ? ';secure' : '' );
};

var proxify = function (fn, ctx) {
  return function () { return fn.apply(ctx, arguments); };
};

var addToFavorite = function (location, title) {
  if (!location) location = window.location;
  if (!title) title = document.title;
  if (window.external && window.external.AddFavorite)
    window.external.AddFavorite(location, title);
};

var Axessia = new (function (name) {
  var data = {};
  this.set = function (key, value) {
    var map = data;
    var fields = key.split('.');
    for (var i = 0; i < fields.length; i++)
      if (i >= fields.length - 1) {
        map[fields[i]] = value instanceof Object ? value[name] : null;
      } else {
        if (!(fields[i] in map)) map[fields[i]] = {};
        map = map[fields[i]];
      }
  };
  this.get = function (key, otherwise) {
    var map = data;
    var fields = key.split('.');
    for (var i = 0; i < fields.length; i++) {
      if (!(map instanceof Object) || !map[fields[i]])
        return otherwise;
      else map = map[fields[i]];
    }
    if (otherwise instanceof Array && !(map instanceof Array))
      return [map];
    else
      return map;
  };
  this.push = function (key, value) {
    if (!(value instanceof Object)) return ;
    var map = data;
    var fields = key.split('.');
    for (var i = 0; i < fields.length; i++)
      if (i >= fields.length - 1) {
        if (map[fields[i]] instanceof Array) map[fields[i]].push(value[name]);
        else if (map[fields[i]]) map[fields[i]] = [map[fields[i]], value[name]];
        else map[fields[i]] = value[name];
      } else {
        if (!(fields[i] in map)) map[fields[i]] = {};
        map = map[fields[i]];
      }
  };
})('value');

Axessia.Calculator = {};
Axessia.Calculator.data =
  { amount: 0
  , duration: 1
  }
Axessia.Calculator.sync = function () {

};
Axessia.Calculator.eval = function () {
  
};

Axessia.RegExp = {};
Axessia.RegExp.host = new RegExp(window.location.host.replace(/\./g, '\\.'));

Axessia.release = {};
Axessia.release.form = function ($form) {
  $form.removeClass('submitting').find('input[type=submit]').attr('disabled', false);
  var list = $form.data('onrelease') || [];
  while (list.length > 0) list.pop().call($form.get(0), $form);
};

Axessia.browse = function (node, fn) {
  var tasks = [node];
  while (tasks.length > 0) {
    node = tasks.shift();
    var level = Array.prototype.slice.call(node.childNodes);
    for (var i = 0, l = level.length; i < l; i++) {
      if (level[i].childNodes) tasks.push(level[i]);
      if (fn) fn(level[i]);
    }
  }
};

Axessia.dom = {};
Axessia.dom.match = function (kinds) {
  var list = (kinds || '').split(/,\s*/);
  var self = arguments.callee;
  return list.fold(function (kind, accu) {
    if (kind in self) return accu.concat(self[kind]);
    return accu;
  }, []).join();
};
Axessia.dom.match.hidden = ['input[type=hidden]'];
Axessia.dom.match.writable = 
  [ 'input[type=text]'
  , 'input[type=password]'
  , 'textarea'
  ];
Axessia.dom.match.checkable =
  [ 'input:checkbox'
  , 'input:radio'
  ];
Axessia.dom.match.selectable = ['select'];
Axessia.dom.clear = function (node) {
  var $node = jQuery(node);
  var Dom = this;
  $node.find('.clear.type-inputs').each(function () {
    $(this).find(Dom.match('checkable,writable,selectable,hidden')).each(function () {
      var $this = $(this);
      var $parents = $this.parents();
      var clear_stop = Array.prototype.findIndex.call($parents, function (e) { $(e).hasClass('clear-stop'); });
      if (~clear_stop) {
        var clear_start = Array.prototype.findIndex.call($parents, function (e) { $(e).hasClass('clear'); });
        if (clear_start >= clear_stop) return ;
      }	
      $this.filter(Dom.match('checkable')).attr('checked', false);
      $this.filter(Dom.match('writable,hidden')).each(function () {
        if ('defaultValue' in this) $(this).val(this.defaultValue);
        else $(this).val('');
      });
      $this.filter(Dom.match('selectable')).find('option[value=]').attr('selected', true);
    });
    $node.find().attr('checked', false);
  });
};
/**
 *  Autofill form buy cookie data
 */
Axessia.dom.autofill = (function () {
  var fieldFinder =
    { '_address': 'textarea[name=_adresse]'
    , '_city': 'input[name=_ville]'
    , '_title': function ($node, value) {
        $node.find('input[type=radio][name=_civilite]').filter(function () {
          if ($(this).val() == value) $(this).attr('checked', true);
        });
      }
    , '_email': 'input[name=_email]'
    , '_firstname': 'input[name=_prenom]'
    , '_name': 'input[name=_nom]'
    , '_phone': function ($node, value) {
        $node.find('[class|=input]:has(input[name=_telephone]) input').val(value);
      }
    , '_zip': 'input[name=_codepostal]'
    }
  ;
  return function (node) {
    var $node = $(node);
    document.cookie.split(';').map(function (e) {
      e = e.split('=');
      var key = unescape(e[0].replace(/\+/g, ' ')).trim();
      var value = unescape(e[1].replace(/\+/g, ' ')).trim();
      if (typeof fieldFinder[key] == 'string')
        $node.find(fieldFinder[key]).val(value);
      else if (typeof fieldFinder[key] == 'function')
        fieldFinder[key]($node, value);
    });
    return arguments.callee;
  }
})();

var Current = new (function () {
  this.hash = 
    { value: ''
    , lookup: null
    , routes: []
    };

  /** 
   * Check every 200ms if hash page has changed, in this case
   * apply function defined in routes array if pattern match
   * with the new hash
   */
  this.hash.lookup = setInterval(function () {
    if (!(window.isDocumentLoaded)) return ;
    var hash = window.location.hash.substr(1), result;
    if (hash == Current.hash.value) return ;
    else Current.hash.value = hash;
    for (var i = 0; i < Current.hash.routes.length; i++)
      if (!!(result = hash.match(Current.hash.routes[i].pattern)))
        Current.hash.routes[i].callback.apply(null, result);
  }, 200);

  this.hash.set = function (anchor) {
    window.location.hash = anchor || '';
    this.value = window.location.hash;
  };

});

var Predicate = {};
Predicate.Math = function (operator, limit, limit2) {
  switch (operator) {
  case '>': return function (index) { return index > limit; };
  case '<': return function (index) { return index < limit; };
  case '>=': return function (index) { return index >= limit; };
  case '<=': return function (index) { return index <= limit; };
  case '=': return function (index) { return index == limit; };
  case 'between': return function (index) { return limit >= index && index <= limit2; };
  }
};

