// Generated by CoffeeScript 1.4.0
var isDefined,
  __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
  __slice = [].slice,
  __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };

window.serious = {};

window.serious.Utils = {};

isDefined = function(obj) {
  return typeof obj !== 'undefined' && obj !== null;
};

jQuery.fn.opacity = function(int) {
  return $(this).css({
    opacity: int
  });
};

window.serious.Utils.clone = function(obj) {
  var flags, key, newInstance;
  if (!(obj != null) || typeof obj !== 'object') {
    return obj;
  }
  if (obj instanceof Date) {
    return new Date(obj.getTime());
  }
  if (obj instanceof RegExp) {
    flags = '';
    if (obj.global != null) {
      flags += 'g';
    }
    if (obj.ignoreCase != null) {
      flags += 'i';
    }
    if (obj.multiline != null) {
      flags += 'm';
    }
    if (obj.sticky != null) {
      flags += 'y';
    }
    return new RegExp(obj.source, flags);
  }
  newInstance = new obj.constructor();
  for (key in obj) {
    newInstance[key] = window.serious.Utils.clone(obj[key]);
  }
  return newInstance;
};

jQuery.fn.cloneTemplate = function(dict, removeUnusedField) {
  var klass, nui, value;
  if (removeUnusedField == null) {
    removeUnusedField = false;
  }
  nui = $(this[0]).clone();
  nui = nui.removeClass("template hidden").addClass("actual");
  if (typeof dict === "object") {
    for (klass in dict) {
      value = dict[klass];
      if (value !== null) {
        nui.find(".out." + klass).html(value);
      }
    }
    if (removeUnusedField) {
      nui.find(".out").each(function() {
        if ($(this).html() === "") {
          return $(this).remove();
        }
      });
    }
  }
  return nui;
};

Object.size = function(obj) {
  var key, size;
  size = 0;
  for (key in obj) {
    if (obj.hasOwnProperty(key)) {
      size++;
    }
  }
  return size;
};

window.serious.States = (function() {

  function States() {
    this.states = {};
  }

  States.prototype.set = function(state, value, scope) {
    if (value == null) {
      value = true;
    }
    if (scope == null) {
      scope = document;
    }
    this.states[state] = value;
    return this._showState(state, value);
  };

  States.prototype._showState = function(state, value, scope) {
    if (value == null) {
      value = true;
    }
    if (scope == null) {
      scope = document;
    }
    $(".when-" + state, scope).each(function(idx, element) {
      var expected_value;
      element = $(element);
      expected_value = element.data('state') || true;
      return $(element).toggleClass('hidden', expected_value.toString() !== value.toString());
    });
    return $(".when-not-" + state, scope).each(function(idx, element) {
      var expected_value;
      element = $(element);
      expected_value = element.data('state') || true;
      return $(element).toggleClass('hidden', expected_value.toString() === value.toString());
    });
  };

  return States;

})();

window.serious.Widget = (function() {

  function Widget() {
    this.cloneTemplate = __bind(this.cloneTemplate, this);

    this.show = __bind(this.show, this);

    this.hide = __bind(this.hide, this);

    this.get = __bind(this.get, this);

    this.set = __bind(this.set, this);

  }

  Widget.bindAll = function() {
    var first, firsts, _i, _len;
    firsts = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
    if (firsts) {
      for (_i = 0, _len = firsts.length; _i < _len; _i++) {
        first = firsts[_i];
        Widget.ensureWidget($(first));
      }
    }
    return $(".widget").each(function() {
      var self;
      self = $(this);
      if (!self.hasClass('template') && !self.parents().hasClass('template')) {
        return Widget.ensureWidget(self);
      }
    });
  };

  Widget.ensureWidget = function(ui) {
    var widget, widget_class;
    ui = $(ui);
    if (!ui.length) {
      return null;
    } else if (ui[0]._widget != null) {
      return ui[0]._widget;
    } else {
      widget_class = Widget.getWidgetClass(ui);
      if (widget_class != null) {
        widget = new widget_class();
        widget.bindUI(ui);
        return widget;
      } else {
        console.warn("widget not found for", ui);
        return null;
      }
    }
  };

  Widget.getWidgetClass = function(ui) {
    return eval("(" + $(ui).attr("data-widget") + ")");
  };

  Widget.prototype.bindUI = function(ui) {
    var action, key, nui, value, _i, _len, _ref, _ref1, _results;
    this.ui = $(ui);
    if (this.ui[0]._widget) {
      delete this.ui[0]._widget;
    }
    this.ui[0]._widget = this;
    this.uis = {};
    if (typeof this.UIS !== "undefined") {
      _ref = this.UIS;
      for (key in _ref) {
        value = _ref[key];
        nui = this.ui.find(value);
        if (nui.length < 1) {
          console.warn("uis", key, "not found in", ui);
        }
        this.uis[key] = nui;
      }
    }
    if (this.ACTIONS != null) {
      _ref1 = this.ACTIONS;
      _results = [];
      for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
        action = _ref1[_i];
        _results.push(this._bindClick(this.ui.find(".do[data-action=" + action + "]"), action));
      }
      return _results;
    }
  };

  Widget.prototype.set = function(field, value, context) {
    /* Set a value to all tag with the given data-field attribute.
    		Field can be a dict or a field name.
    		If it is a dict, the second parameter should be a context.
    		The default context is the widget itself.
    */

    var name, _value;
    if (typeof field === "object") {
      context = value || this.ui;
      for (name in field) {
        _value = field[name];
        context.find(".out[data-field=" + name + "]").html(_value);
      }
    } else {
      context = context || this.ui;
      context.find(".out[data-field=" + field + "]").html(value);
    }
    return context;
  };

  Widget.prototype.get = function(form) {
    var data;
    form = $(form);
    data = {};
    form.find('input.in').each(function() {
      var input;
      input = $(this);
      if (!input.hasClass('template') && !input.parents().hasClass('template')) {
        return data[input.attr('name')] = input.val();
      }
    });
    return data;
  };

  Widget.prototype.hide = function() {
    return this.ui.addClass("hidden");
  };

  Widget.prototype.show = function() {
    return this.ui.removeClass("hidden");
  };

  Widget.prototype.cloneTemplate = function(template_nui, dict, removeUnusedField) {
    var action, klass, nui, value, _i, _len, _ref;
    if (removeUnusedField == null) {
      removeUnusedField = false;
    }
    nui = template_nui.clone();
    nui = nui.removeClass("template hidden").addClass("actual");
    if (typeof dict === "object") {
      for (klass in dict) {
        value = dict[klass];
        if (value !== null) {
          nui.find(".out." + klass).html(value);
        }
      }
      if (removeUnusedField) {
        nui.find(".out").each(function() {
          if ($(this).html() === "") {
            return $(this).remove();
          }
        });
      }
    }
    if (this.ACTIONS != null) {
      _ref = this.ACTIONS;
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        action = _ref[_i];
        this._bindClick(nui.find(".do[data-action=" + action + "]"), action);
      }
    }
    return nui;
  };

  Widget.prototype._bindClick = function(nui, action) {
    var _this = this;
    if ((action != null) && __indexOf.call(this.ACTIONS, action) >= 0) {
      return nui.click(function(e) {
        _this[action](e);
        return e.preventDefault();
      });
    }
  };

  return Widget;

})();

window.serious.URL = (function() {

  function URL() {
    this.toString = __bind(this.toString, this);

    this.fromString = __bind(this.fromString, this);

    this.enableDynamicLinks = __bind(this.enableDynamicLinks, this);

    this.updateUrl = __bind(this.updateUrl, this);

    this.hasBeenAdded = __bind(this.hasBeenAdded, this);

    this.hasChanged = __bind(this.hasChanged, this);

    this.remove = __bind(this.remove, this);

    this.update = __bind(this.update, this);

    this.set = __bind(this.set, this);

    this.onStateChanged = __bind(this.onStateChanged, this);

    this.get = __bind(this.get, this);

    var _this = this;
    this.previousHash = [];
    this.handlers = [];
    this.hash = this.fromString(location.hash);
    $(window).hashchange(function() {
      var handler, _i, _len, _ref, _results;
      _this.previousHash = window.serious.Utils.clone(_this.hash);
      _this.hash = _this.fromString(location.hash);
      _ref = _this.handlers;
      _results = [];
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        handler = _ref[_i];
        _results.push(handler());
      }
      return _results;
    });
  }

  URL.prototype.get = function(field) {
    if (field == null) {
      field = null;
    }
    if (field) {
      return this.hash[field];
    } else {
      return this.hash;
    }
  };

  URL.prototype.onStateChanged = function(handler) {
    return this.handlers.push(handler);
  };

  URL.prototype.set = function(fields, silent) {
    var hash, key, value;
    if (silent == null) {
      silent = false;
    }
    hash = silent ? this.hash : window.serious.Utils.clone(this.hash);
    hash = [];
    for (key in fields) {
      value = fields[key];
      if (isDefined(value)) {
        hash[key] = value;
      }
    }
    return this.updateUrl(hash);
  };

  URL.prototype.update = function(fields, silent) {
    var hash, key, value;
    if (silent == null) {
      silent = false;
    }
    hash = silent ? this.hash : window.serious.Utils.clone(this.hash);
    for (key in fields) {
      value = fields[key];
      if (isDefined(value)) {
        hash[key] = value;
      } else {
        delete hash[key];
      }
    }
    return this.updateUrl(hash);
  };

  URL.prototype.remove = function(key, silent) {
    var hash;
    if (silent == null) {
      silent = false;
    }
    hash = silent ? this.hash : window.serious.Utils.clone(this.hash);
    if (hash[key]) {
      delete hash[key];
    }
    return this.updateUrl(hash);
  };

  URL.prototype.hasChanged = function(key) {
    if (this.hash[key] != null) {
      if (this.previousHash[key] != null) {
        return this.hash[key].toString() !== this.previousHash[key].toString();
      } else {
        return true;
      }
    } else {
      if (this.previousHash[key] != null) {
        return true;
      }
    }
    return false;
  };

  URL.prototype.hasBeenAdded = function(key) {
    return console.error("not implemented");
  };

  URL.prototype.updateUrl = function(hash) {
    if (hash == null) {
      hash = null;
    }
    if (!hash || Object.size(hash) === 0) {
      return location.hash = '_';
    } else {
      return location.hash = this.toString(hash);
    }
  };

  URL.prototype.enableDynamicLinks = function(context) {
    var _this = this;
    if (context == null) {
      context = null;
    }
    return $("a.internal[href]", context).click(function(e) {
      var href, link;
      link = $(e.currentTarget);
      href = link.attr("data-href") || link.attr("href");
      if (href[0] === "#") {
        if (href.length > 1 && href[1] === "+") {
          _this.update(_this.fromString(href.slice(2)));
        } else if (href.length > 1 && href[1] === "-") {
          _this.remove(_this.fromString(href.slice(2)));
        } else {
          _this.set(_this.fromString(href.slice(1)));
        }
      }
      return false;
    });
  };

  URL.prototype.fromString = function(value) {
    var hash, hash_list, item, key, key_value, val, _i, _len;
    value = value || location.hash;
    hash = {};
    value = value.replace('!', '');
    hash_list = value.split("&");
    for (_i = 0, _len = hash_list.length; _i < _len; _i++) {
      item = hash_list[_i];
      if (item != null) {
        key_value = item.split("=");
        if (key_value.length === 2) {
          key = key_value[0].replace("#", "");
          val = key_value[1].replace("#", "");
          hash[key] = val;
        }
      }
    }
    return hash;
  };

  URL.prototype.toString = function(hash_list) {
    var i, key, new_hash, value;
    if (hash_list == null) {
      hash_list = null;
    }
    hash_list = hash_list || this.hash;
    new_hash = "!";
    i = 0;
    for (key in hash_list) {
      value = hash_list[key];
      if (i > 0) {
        new_hash += "&";
      }
      new_hash += key + "=" + value;
      i++;
    }
    return new_hash;
  };

  return URL;

})();
