(function() {
  Date.prototype.getYearDay = function() {
    var yyyy = this.getFullYear(),
      d = new Date(yyyy, this.getMonth(), this.getDate(), 12),  // this, midday
      d0 = new Date(yyyy, 0, 1);  // Jan 1, midnight
    return Math.floor((d - d0) / 86400 * 1000) + 1;
  }
  Date.prototype.getYearWeek = function(dow) {
    dow = dow || 0;
    var yyyy = this.getFullYear(),
      d = new Date(yyyy, this.getMonth(), this.getDate(), 12),
      d0 = new Date(yyyy, 0, 1),
      delta = ((dow || 0) + 7 - d0.getDay()) % 7,
      d1 = new Date(yyyy, 0, 1 + delta);
    return Math.floor((d - d1) / (7 * 86400 * 1000)) + 1;
  }
  var z = "000";
  function zpad(n, width) {
    width = width || 2;
    while (z.length < width)
      z += z;
    var s = "" + n;
    return z.substring(0, width - s.length) + s;
  }
  var strftime_funks = {
    a: function(d) { return ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"][d.getDay()] },
    A: function(d) { return["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"][d.getDay()] },
    b: function(d) { return["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"][d.getMonth()] },
    B: function(d) { return ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"][d.getMonth()] },
    c: function(d) { return d.strftime("%x %X") },
    d: function(d) { return zpad(d.getDate()) },
    H: function(d) { return zpad(d.getHours()) },
    I: function(d) { return zpad((d.getHours() % 12) || 12) },
    j: function(d) { return zpad(d.getYearDay(), 3) },
    m: function(d) { return zpad(d.getMonth() + 1) },
    M: function(d) { return zpad(d.getMinutes()) },
    p: function(d) { return d.getHours() < 12 ? "AM" : "PM" },
    S: function(d) { return zpad(d.getSeconds()) },
    U: function(d) { return zpad(d.getYearWeek(0)) },
    W: function(d) { return zpad(d.getYearWeek(1)) },
    w: function(d) { return "" + d.getDay() },
    x: function(d) { return d.strftime("%m/%d/%Y") },
    X: function(d) { return d.strftime("%H:%M:%S") },
    y: function(d) { return zpad(d.getFullYear() % 100) },
    Y: function(d) { return d.getFullYear() },
    Z: function(d) { return d.toString().match(/\((.+)\)$/)[1] },
    "%": function(d) { return "%" }
  };
  Date.prototype.strftime = function(fmt) {
    var d = this;
    return fmt.replace(/%(.)/g, function(_, c) {
      var f = strftime_funks[c];
      return f ? f(d) : "";
    });
  };
})();

$(function() {
  $.log = function() { window.console && window.console.log.apply(this, arguments); };
  if ($.dateEntry) {
    $("form .date#client_birthdate").dateEntry({spinnerImage: ""});
  }
  $("form.search [type=text]#from, form.search [type=text]#to, form .date#date")
    .datepicker({
      showOn: "button",
      buttonText: "...",
      showAnim: "slide",
      showOptions: { direction: "up" }
    });
  $("button.ui-datepicker-trigger").button({icons: {primary: "ui-icon-calendar"}, text: false, label: "Pick a date"});
  $("div.pagination").addClass("ui-buttonset").find("a, span.current, span.gap, span.prev_page, span.next_page").addClass("ui-button");
  $("div.pagination").find("span.gap").data("buttonOptions", {disabled: true});
  $("td.buttonbox").livequery(function() { $(this).addClass("ui-buttonset"); });
  $("a.action").livequery(function() {
    var $this = $(this).addClass("ui-button");
    if ($this.is(".mini.chart")) {
      $this.data("buttonOptions", {icons: {primary: "ui-icon-image"}, text: false});
    }
    if ($this.is(".mini.summary")) {
      $this.data("buttonOptions", {icons: {primary: "ui-icon-info"}, text: false});
    }
    if ($this.is(".mini.flags")) {
      $this.data("buttonOptions", {icons: {primary: "ui-icon-flag"}, text: false});
    }
  });
  $("button[type=submit]").livequery(function() {
    var $this = $(this).addClass("ui-button");
    if ($this.is(".mini.search")) {
      $this.data("buttonOptions", {icons: {primary: "ui-icon-search"}, text: false});
    } else if ($this.is(".search")) {
      $this.data("buttonOptions", {icons: {primary: "ui-icon-search"}});
    } else if ($this.is(".mini.archive")) {
      $this.data("buttonOptions", {icons: {primary: "ui-icon-arrowreturnthick-1-e"}, text: false});
    } else if ($this.is(".mini.unarchive")) {
      $this.data("buttonOptions", {icons: {primary: "ui-icon-arrowreturnthick-1-w"}, text: false});
    } else if ($this.is(".mini.clear")) {
      $this.data("buttonOptions", {icons: {primary: "ui-icon-check"}, text: false});
    } else if ($this.is(".mini.ignore")) {
      $this.data("buttonOptions", {icons: {primary: "ui-icon-trash"}, text: false});
    } else if ($this.is(".mini.recall")) {
      $this.data("buttonOptions", {icons: {primary: "ui-icon-refresh"}, text: false});
    } else if ($this.is(".mini.note")) {
      $this.data("buttonOptions", {icons: {primary: "ui-icon-comment"}, text: false});
    } else if ($this.is(".mini.grant")) {
      $this.data("buttonOptions", {icons: {primary: "ui-icon-locked"}, label: "Click to " + $this.text().toLowerCase() + " access"});
    } else if ($this.is(".mini.revoke")) {
      $this.data("buttonOptions", {icons: {primary: "ui-icon-unlocked"}, label: "Click to " + $this.text().toLowerCase() + " access"});
    }
  });
  $("ul.actions a").addClass("ui-button");
  $(".ui-button.disabled").attr({disabled: "disabled"});
  $(".ui-button").livequery(function() { $(this).button($(this).data("buttonOptions")); });
  var $filter_alerts_toggles = $("form.filter-alerts input[type=checkbox]");
  $filter_alerts_toggles.click(function() {
    var checked = $(this).attr("checked");
    ($("table.list tbody tr:not(.alerted)"))[checked ? "hide" : "show"]();
    $filter_alerts_toggles.attr("checked", checked);
  });
  $filter_alerts_toggles.attr("checked", true);
  if ($filter_alerts_toggles.length)
    $("table.list tbody tr:not(.alerted)").hide();
  $("table.history tbody a.toggle").livequery(function() { $(this).click(function() {
    var $this = $(this);
    var $that = $this.parent().find("div.extra");
    $that.toggle("slide", {direction: "up"}, "slow", function() {
      $this.text($that.is(":visible") ? "hide note" : "show note");
    });
    return false;
  })});
  $("table.list tbody form.archive").livequery(function() { $(this).submit(function() {
    var $hf = $(this).find("input[type=hidden][name=show_pid]");
    var $d = $("<div id=archive_form/>").appendTo("body")
      .append($("<img src=\"/img/spinner.gif\" width=28 height=28 alt=\"Please wait...\" style=\"display: block; margin: 4em auto\"/>"))
      .load(this.action + " form", null, function() {
        $(this).find("form")
        .append($hf)
        .ajaxForm({
          success: function(response, status) {
            $d.dialog("close");
            $response = $(response);
            s = "#" + $response.attr("id");
            $(s).replaceWith($response);
            $(s).effect("highlight", {}, 5000);
          }
        })
        .find("input[type=submit][value=Cancel]").click(function() {
          $d.dialog("close");
          return false;
        });
      })
      .dialog({
        modal: true,
        resizable: false,
        title: "Archive client",
        width: 540,
        close: function(e, ui) { $("div#archive_form").dialog("destroy").remove(); }
      });
    return false;
  }).find("button").click(function() {
    //FIXME clicking the button fetches page even if with $form.submit(return false),
    //..... so we must trigger a submit and cancel the click here -- why?!
    $(this.form).submit();
    return false;
  })});
  $("table.list tbody form.unarchive").livequery(function() { $(this).submit(function() {
    var $hf = $(this).find("input[type=hidden][name=show_pid]");
    var $d = $("<div id=unarchive_form/>").appendTo("body")
      .append($("<img src=\"/img/spinner.gif\" width=28 height=28 alt=\"Please wait...\" style=\"display: block; margin: 4em auto\"/>"))
      .load(this.action + " form", null, function() {
        $(this).find("form")
        .append($hf)
        .ajaxForm({
          success: function(response, status) {
            $d.dialog("close");
            $response = $(response);
            s = "#" + $response.attr("id");
            $(s).replaceWith($response);
            $(s).effect("highlight", {}, 5000);
          }
        })
        .find("input[type=submit][value=Cancel]").click(function() {
          $d.dialog("close");
          return false;
        });
      })
      .dialog({
        modal: true,
        resizable: false,
        title: "Unarchive client",
        width: 540,
        close: function(e, ui) { $("div#unarchive_form").dialog("destroy").remove(); }
      });
    return false;
  }).find("button").click(function() {
    //FIXME clicking the button fetches page even if with $form.submit(return false),
    //..... so we must trigger a submit and cancel the click here -- why?!
    $(this.form).submit();
    return false;
  })});
  $("table.history tbody form.addnote").livequery(function() { $(this).submit(function() {
    var $tr = $(this).parents("tr.date");
    var $d = $("<div id=addnote_form/>").appendTo("body")
      .append($("<img src=\"/img/spinner.gif\" width=28 height=28 alt=\"Please wait...\" style=\"display: block; margin: 4em auto\"/>"))
      .load(this.action + " form", null, function() {
        $(this).find("form")
        .find("#date").attr({readonly: "readonly"}).end()
        .ajaxForm({
          success: function(response, status) {
            $d.dialog("close");
            $response = $(response);
            s = "#" + $response.attr("id");
            $tr.after($response);
            $(s).effect("highlight", {}, 5000);
          }
        })
        .find("button[type=submit]:contains('Cancel')").click(function() {
          $d.dialog("close");
          return false;
        });
      })
      .dialog({
        modal: true,
        resizable: false,
        title: "Add journal entry",
        width: 540,
        close: function(e, ui) { $("div#addnote_form").dialog("destroy").remove(); }
      });
    return false;
  })});
  $("table.history tbody form.clear").livequery(function() { $(this).submit(function() {
    var $tr = $(this).parents("tr.datapoint");
    var $hf = $(this).find("input[type=hidden][name=client_id]");
    var $d = $("<div id=clear_form/>").appendTo("body")
      .append($("<img src=\"/img/spinner.gif\" width=28 height=28 alt=\"Please wait...\" style=\"display: block; margin: 4em auto\"/>"))
      .load(this.action + " form.edit_datapoint", null, function() {
        $(this).find("form.edit_datapoint")
        .append($hf)
        .ajaxForm({
          success: function(response, status) {
            $d.dialog("close");
            $response = $(response);
            s = "#" + $response.attr("id");
            $(s).replaceWith($response);
            $(s).effect("highlight", {}, 5000);
          }
        })
        .find("input[type=submit][value=Cancel]").click(function() {
          $d.dialog("close");
          return false;
        });
      })
      .dialog({
        modal: true,
        resizable: false,
        title: "Clear alert",
        width: 540,
        close: function(e, ui) { $("div#clear_form").dialog("destroy").remove(); }
      });
    return false;
  })});
  $("tr form.inline").livequery(function() {
    $(this).ajaxForm({
      success: function(response, status) {
        $response = $(response);
        s = "#" + $response.attr("id");
        $(s).replaceWith($response);
        $(s).effect("highlight", {}, 5000);
      }
    });
  });
});
