/*
 * rdc.js - Part of rdc.it website
 *
 * Autore: Giovanni Giacobbi <giovanni@giacobbi.net>
 * Copyright (c) 2010
 *
 * Tutti i diritti sono riservati.
 *
 */

/* graceful fall-back when firebug is not available
 * @snippet firebug-fallback 20101221 */
if (!window.console || !console.firebug) {
  // from http://getfirebug.com/wiki/index.php/Console_API
  var names = ["log", "debug", "info", "warn", "error", "assert", "clear",
               "dir", "dirxml", "trace", "group", "groupCollapsed", "groupEnd",
               "time", "timeEnd", "profile", "profileEnd", "count", "exception", "table"];

  window.console = { };
  for (var i = 0; i < names.length; i++) {
    window.console[names[i]] = function() { };
  }
}

/* jQuery custom extensions */
(function($) {
  /**
   * Applies IE png hack to selected DOM elements' backgrounds
   */
  $.fn.fixpng = function() {
    if ($.browser.msie) {
      return this.each(function(w) {
        var results = this.currentStyle.backgroundImage.match(/url\("(.+)"\)/);
        if (results != null) {
          var url = results[1];
          this.style.backgroundImage = 'none';
          this.style.filter = "progid:DXImageTransform.Microsoft." +
                   "AlphaImageLoader(src='" + url + "',sizingMethod='scale')";
        }
      });
    }
    return this;
  }
})(jQuery);

/* admin utility */
function toggleAll(objForm, do_check) {
  for (i = 0; i < objForm.elements.length; i++) {
    if ((objForm.elements[i].type == "checkbox") &&
        (objForm.elements[i].name == "selected[]"))
      objForm.elements[i].checked = do_check;
  }
  return;
}

/* admin utility */
function submitMassOperation(action) {
  var eform = document.forms.massop;
  if (eform) {
    if (action == 'move') {
      eform.action.value = 'promptmassmove';
      eform.dup.value = '0';
    }
    if (action == 'dup') {
      eform.action.value = 'promptmassmove';
      eform.dup.value = '1';
    }
    if (action == 'remove') {
      eform.action.value = 'promptmassremove';
    }

    var cnt = 0;
    eform.submit();
  }
}

/* global site init function */
$(function() {
  /* IE alphapng fix */
  $("ul.wlink li.active a").fixpng();

  /* combo box rebuild */
  //$(".advsearch select").ufd({skin:"rdc"});

  /* advanced search dropdown block */
  $("#adv_toggle_search").click(function () {
    if ($("#advSearchPanel").is(":hidden")) {
      /* show the panel */
      $("#advSearchPanel").slideDown("slow");
      $("#adv_toggle_search").html("Ricerca avanzata &#x25bc;")
                             .parents("div.wx_Widget").addClass("wp_pushed");
      $("#advSearch [name=\"adv_search_enabled\"]").val("1");
      $.cookie("rdc_adv_search", "1");
    }
    else {
      $("#advSearchPanel").slideUp("slow");
      $("#adv_toggle_search").html("Ricerca avanzata &#x25b6;")
                             .parents("div.wx_Widget").removeClass("wp_pushed");
      $("#advSearch [name=\"adv_search_enabled\"]").val("0");
      $.cookie("rdc_adv_search", "0");
    }
    return false;
  });

  /* restore status from cookie */
  if ($.cookie("rdc_adv_search") == "1") {
    console.log("advSearch cookie is open - showing");
    $("#advSearchPanel").show();
    $("#adv_toggle_search").html("Ricerca avanzata &#x25bc;")
                           .parents("div.wx_Widget").addClass("wp_pushed");
    $("#advSearch [name=\"adv_search_enabled\"]").val("1");
  }

  $("#g_frm_search_q").keyup(function(evt) {
    var newlength = Math.min(330, this.value.length * 8);
    if (newlength > $(this).width())
      $(this).css("width", newlength + "px");
  });
});

/* widgets */
$(function() {
  if ($.browser.msie && $.browser.version < 7)
    return;

  console.time("widgets");

  var deps = {
    "Widget" : null,
    "InputTextHeader" : "Widget",
    "InputTextLogin" : "InputTextHeader",
    "Button" : "Widget",
    "ButtonLogin" : "Button"
  };

  var regEx = /^w_(.+)$/;

  $(".w_Widget").each(function() {
    var $this = $(this);

    if ($this.hasClass("wp_noconvert"))
      return;

    console.debug("Widget: converting widget \"" + $this.attr("class") + "\"" +
        (this.id ? " with id \"" + this.id + "\"" : ""));

    /* first, remove all widget classes */
    var classNames = $this.attr("class").split(/\s+/);
    var conv = "";

    for (var i = 0; i < classNames.length; i++) {
      var matches = classNames[i].match(regEx);
      if (matches) {
        if (typeof deps[matches[1]] == "undefined") {
          console.warn("Invalid widget class \"" + matches[1] + "\"");
          continue;
        }

        if (deps[matches[1]] && !$this.hasClass("w_" + deps[matches[1]])) {
          console.warn("Broken widget dependency, class \"" + matches[1] + "\" " +
                       "requires class \"" + deps[matches[1]] + "\"");
          continue;
        }

        if ((matches[1] == "InputTextHeader") && ($this.attr("title") != "")) {
          this.origCleanValue = $this.attr("title");
          console.debug(".. InputTextHeader: saved default value \"" + this.origCleanValue + "\"");

          $this.attr("title", "");

          $this.focus(function() {
            if (this.value == this.origCleanValue)
              this.value = "";
          });
          $this.blur(function() {
            if (this.value == "")
              this.value = this.origCleanValue;
          });

          if ($this.attr("value") == "")
            $this.attr("value", this.origCleanValue);
        }

        classNames[i] = "wx_" + matches[1];
        conv += "wx_" + matches[1] + " ";
      }
    }

    $this.attr("class", classNames.join(" "));
    $this.wrap(
      "<div class=\"" + conv + "\">" +
         "<div class=\"wx_layout\">" +
         "</div>" +
      "</div>");
  });

  console.timeEnd("widgets");
});

/* shadowBox */
$(function() {
  console.time("shadowBox");

  var html =
    "<div class=\"outerShadowBox\">" +
      "<span class=\"g_left\">" +
        "<span class=\"g_right\">" +
        "</span>" +
      "</span>" +
    "</div>";

  var htmlPre =
    "<span class=\"g_corner g_topleft\"></span>" +
    "<span class=\"g_corner g_topright\"></span>" +
    "<span class=\"g_corner g_bottomleft\"></span>" +
    "<span class=\"g_corner g_bottomright\"></span>" +
    "<span class=\"g_top\"></span>";

  var htmlPost =
    "<span class=\"g_bottom\"></span>";

  var $shadowBoxes = $("div.shadowBox");
  console.debug("Replacing " + $shadowBoxes.length + " shadowBox(es)");

  $shadowBoxes.wrap(html).addClass("innerShadowBox");
  $shadowBoxes.parents("div.outerShadowBox").prepend(htmlPre)
                                            .append(htmlPost);

  function getShadowSize($outerBlock) {
    var result = new Array;

    result[0] = $outerBlock.children("span.g_top").height();
    result[2] = $outerBlock.children("span.g_bottom").height();

    var $left = $outerBlock.children("span.g_left"),
        $right = $left.children("span.g_right");

    result[1] = parseInt($right.css("padding-right"));
    result[3] = parseInt($left.css("padding-left"));

    if (isNaN(result[1]) || isNaN(result[3])) {
      console.warn("Failed to compute shadow sizes for shadowBox");
      result = null;
    }
    else {
      console.debug("Computer shadow width for shadowBox:");
      console.log(result);
    }

    return result;
  }

  var shadowSizes;

  $shadowBoxes.each(function() {
    var $inner = $(this);
    var $outer = $inner.parents("div.outerShadowBox");

    if (shadowSizes == null)
      shadowSizes = getShadowSize($outer.eq(0));

    console.debug("Processing pos " + $inner.css("position"));

    var attrs = [ "top", "right", "bottom", "left", "width", "position" ];
    var defValues = [ "auto", "auto", "auto", "auto", "auto", "static" ];

    for (var a in attrs) {
      /* leave the static alone, outer block must be non-static to be a root block */
      if ((a == 5) && ($inner.css(attrs[a]) == "static"))
        continue;

      /* get the original value given to the inner box */
      var value = $inner.css(attrs[a]);
      console.log("Original value for " + attrs[a] + " is \"" + value + "\"");

      /* alter positioning with the shadow size */
      if (((a == 3) || (a == 0)) && /^\d+px$/.test(value)) {
        value = (parseInt(value) + shadowSizes[a]) + "px";
        console.debug(".. altered value for " + attrs[a] + " is " + value);
      }
      if ((a == 1) || (a == 2))
        continue;

      if ((a == 4) && /^\d+px$/.test(value)) {
        value = (parseInt(value) + shadowSizes[1] + shadowSizes[3]) + "px";
        console.debug(".. altered value for " + attrs[a] + " is " + value);
      }

      $outer.css(attrs[a], value);
      $inner.css(attrs[a], defValues[a]);
    }
  });

  console.timeEnd("shadowBox");
});

/* menu bar slider animation */
$(function() {
  var colorNormal = "#6f6f6f";
  var colorHover = "#ff0000";

  //console.debug("creating the div");
  var $d = $(document.createElement("DIV"));
  $d.addClass("active");
  $("div.wlink").append($d);
  var $dd = $(document.createElement("DIV"));
  $d.append($dd);
  $dd.fixpng();

  //console.debug("intercepting the active one");
  var $div = $("div.wlink");
  var $a = $("ul.wlink .active a");
  if ($a.length > 0) {
    var activeOffset = Math.round($a.offset().left - $div.offset().left);
    $d.css("left", activeOffset + "px");
    $d.css("opacity", 1);
    $a.css("color", colorHover);
    $("ul.wlink li.active a").get(0).style.filter = "";
    $("ul.wlink .active").removeClass("active");
  }
  else
    $d.css("opacity", 0);

  $("ul.wlink a").mouseover(function() {
    if ($a.length > 0)
      $a.css("color", colorNormal);
    $(this).css("color", colorHover);

    $d.stop();
    var myOffset = Math.round($(this).offset().left - $div.offset().left);
    if ($d.css("opacity") > 0.2) {
      //console.debug("moving the slider to " + myOffset);
      $d.animate({ "left": myOffset + "px", "opacity": 1 }, 500, "linear");
    }
    else {
      //console.debug("spawning slider at " + myOffset);
      $d.css("left", myOffset + "px");
      $d.animate({ "opacity": 1 });
    }
  });

  $("ul.wlink a").mouseout(function() {
    $(this).css("color", colorNormal);

    $d.stop();
    if ($a.length > 0) {
      var activeOffset = Math.round($a.offset().left - $div.offset().left);
      $a.css("color", colorHover);
      $d.animate({ "left": activeOffset + "px" }, 350, "linear");
    }
    else
      $d.animate({ "opacity": 0 });
  });

  /* rifinitura finale: quando lo clicco diventa il nuovo attivo */
  $("ul.wlink a").click(function() {
    $a = $(this);
  });
});

/* overlay and dialogs */
$(function() {

  $("body").append("<div id=\"wx_Overlay\"></div>" +
                   "<div id=\"wx_Window\"><div class=\"wx_Window_Layout\"></div></div>");

  var $wxLayout = $("#wx_Window > div.wx_Window_Layout");
  var $wxOverlay = $("#wx_Overlay");
  var $wxWindow = $("#wx_Window");
  var domHolder = null;

  $wxWindow.get(0).windowShow = function(dom_content) {
    console.debug("Showing popup window with content");

    /* center the window on the screen */
    var contentWidth = $(dom_content).width();
    var contentHeight = $(dom_content).height();
    console.debug(".. computed popup size is " + contentWidth + "x" + contentHeight);

    var offsetLeft = Math.floor(($(window).width() - contentWidth) / 2);
    var offsetTop = Math.floor(($(window).height() - contentHeight) / 2);
    console.debug(".. computed window position is x=" + offsetLeft + ", y=" + offsetTop);

    domHolder = dom_content;
    $wxLayout
      .css("width", contentWidth + "px")
      .css("height", contentHeight + "px")
      .append($(dom_content).children());

    $wxOverlay.fadeIn("fast");

    $wxWindow
      .css("left", offsetLeft + "px")
      .css("top", offsetTop + "px")
      .show("slow");
  };

  $wxWindow.get(0).windowHide = function() {
    console.debug("Closing popup window");
    $wxOverlay.fadeOut("slow");
    $wxWindow.hide("fast");

    /* put back the dom content to the original position */
    if (domHolder)
      $(domHolder).append($wxLayout.children());
  };

  $wxOverlay.click($wxWindow.get(0).windowHide);


});


/* search form intelligence */
$(function() {
  var htmlUpdating = false;

  function updateSearchPanel(opts) {
    // FIXME: error handling?

    console.debug("updateSearchPanel() [ajax]: received response for search panel update");
    for (var field in opts) {
      var $obj = $("#advSearch_" + field);
      console.debug(".. updating field \"" + field + "\" with " + opts[field].length + " values");

      var options = "<option value=\"\"></option>";
      for (var i = 0; i < opts[field].length; i++) {
        options += "<option value=\"" + opts[field][i] + "\">" + opts[field][i] + "</option>";
      }

      $obj.html(options);

      if (opts[field].length > 0)
        $obj.prop("disabled", false);
      else
        $obj.prop("disabled", true);
    }

    htmlUpdating = false;

    /* trigger the update event */
    $("#advSearch").trigger("rdcadvsearch");
  }

  /* year and booklet changes cause a refresh */
  $("#advSearch_year,#advSearch_booklet").change(function() {
    if (htmlUpdating)
      return;

    console.debug("search: updating fields with filter for \"" + this.id + "\"");

    /* determine which fields have to be updated, which will also alter the
     * webservice request fields list */
    //var updFields = [ "author", "entity", "part", "president" ];
    var updFields = [ ];
    if (this.id == "advSearch_year") {
      updFields.push("booklet");
    }

    for (var i = 0; i < updFields.length; i++) {
      var $obj = $("#advSearch_" + updFields[i]);

      // FIXME: save the selected value before updating, afterwards, if it's
      // still available, set it again

      /* disable the field while being loaded via AJAX */
      $obj.attr("disabled", "disabled");
      $obj.html("<option value=\"\">Attendere...</option>");
    }

    if (updFields.length > 0) {
      htmlUpdating = true;

      var opts = {
        year: $("#advSearch_year").val(),
        booklet: $("#advSearch_booklet").val(),
        fields: updFields.join(",")
      };
      $.getJSON("/ws/search:opts", opts, updateSearchPanel);
    }
    else
      console.warn(".. nothing to update!");

  });

  /* convert author to autocomplete */
  $("#advSearch_author,#advSearch_president,#advSearch_part,#advSearch_entity").autocomplete({
    minLength: 2,
    source: function(request, response) {
      var field = this.element[0].id.substring(10);
      console.log("autocomplete querying for \"" + field + "\"");
      var opts = {
        year: $("#advSearch_year").val(),
        booklet: $("#advSearch_booklet").val(),
        fields: field,
        q: request.term,
        limit: 20
      };

      $.getJSON("/ws/search:opts", opts, function(data) {
        response(data[field]);
      });
    }
  });

  /* reset */
  $("#advSearchPanel input[type=\"reset\"]").click(function() {
    console.debug("search: reset fields");
    $("#g_frm_search_q").val("").blur();
    $("#advSearchPanel select").val("");
    $("#advSearch_year").change();
    return false;
  });

  /* bind one shot event to set the original values of the form (only the first time) */
  $("#advSearch").bind("rdcadvsearch", function() {
    console.log("triggered rdcadvsearch!");
    $("#advSearch [desired]").each(function() {
      var $this = $(this),
          desired = $this.attr("desired");

      if (desired) {
        $this.val(desired).attr("desired", "");
      }
    });
  });

  var $advSearch_popup = $(".advSearch_popup");

  var advSearch_popup_pagesize = 20;
  var advSearch_popup_lock = 0;
  var advSearch_popup_anim_lock = 0;

  function advSearch_popup_open() {
    if (advSearch_popup_anim_lock) {
      console.warn("advSearch_popup_close(): locked");
      return;
    }

    advSearch_popup_anim_lock = 1;

    $advSearch_popup.slideDown("slow", function() {
      advSearch_popup_anim_lock = 0;
    });
  }

  function advSearch_popup_close() {
    if (advSearch_popup_anim_lock) {
      console.warn("advSearch_popup_close(): locked");
      return;
    }

    advSearch_popup_anim_lock = 1;

    $advSearch_popup.slideUp("slow", function() {
      $advSearch_popup.data("rdc_curr_field", "");
      advSearch_popup_anim_lock = 0;
    });
  }

  function advSearch_popup_load(field, offset) {
    if (advSearch_popup_lock) {
      console.warn("advSearch_popup_load(): locked");
      return;
    }

    var opts = {
      year: $("#advSearch_year").val(),
      booklet: $("#advSearch_booklet").val(),
      fields: field,
      offset: offset,
      limit: advSearch_popup_pagesize
    };

    /* remember the offset and lock */
    $advSearch_popup.data("rdc_curr_field", field);
    $advSearch_popup.data("rdc_curr_offset", offset);
    advSearch_popup_lock = 1;

    /* clear it and put the ajax preloader */
    $advSearch_popup.find("ul").remove();

    $.getJSON("/ws/search:opts", opts, function(data) {
      advSearch_popup_lock = 0;

      /* update the layout */
      if (data[field]) {

        /* if we have no results, go back */
        if (data[field].length == 0) {
          var next_offset = offset - advSearch_popup_pagesize;
          if (next_offset > 0) {
            advSearch_popup_load(field, next_offset);
            return;
          }
        }

        var html = "<ul rel=\"" + field + "\">";
        for (var i = 0; i < data[field].length; i++) {
          html += "<li><a href=\"#select\">" + data[field][i] + "</a></li>";
        }

        html += "</ul>";

        $advSearch_popup.find(".content").prepend(html);
      }
    });

  }

  $advSearch_popup.find(".nav a").click(function() {
    var href = $(this).attr("href");

    console.debug("action \"" + href + "\"");

    if (href == "#close") {
      advSearch_popup_close();
    }
    else if (href == "#next") {
      var next_offset = $advSearch_popup.data("rdc_curr_offset") + advSearch_popup_pagesize;
      advSearch_popup_load($advSearch_popup.find("ul").attr("rel"), next_offset);
    }
    else if (href == "#prev") {
      var prev_offset = $advSearch_popup.data("rdc_curr_offset") - advSearch_popup_pagesize;
      if (prev_offset < 0)
        prev_offset = 0;
      advSearch_popup_load($advSearch_popup.find("ul").attr("rel"), prev_offset);
    }

    return false;
  });

  $(".advSearch_js_search").click(function(evt) {
    /* in the meanwhile of the animation, launch an AJAX query */
    var field = $(this).attr("href").substring(1);
    console.debug("opening popup for '" + field + "'");

    /* if we are clicking again the same button */
    if ($advSearch_popup.data("rdc_curr_field") == field) {
      advSearch_popup_close();
      return false;
    }

    /* instantly hide popup if open elsewhere */
    $advSearch_popup.hide();

    /* let's reposition it */
    var pos = $(this).offset();

    if (field == "author")
      $advSearch_popup.css("left", (pos['left'] + 65) + "px");
    else
      $advSearch_popup.css("left", (pos['left'] - 250) + "px");

    /* load the contents */
    advSearch_popup_load(field, 0);

    /* open with the animation while loading */
    advSearch_popup_open();

    return false;
  });

  $("#advSearch_popup ul a").live("click", function() {
    var $ul = $(this).closest("ul");
    var f = $ul.attr("rel");
    var $t = $("#advSearch_" + f);

    console.log("clicked " + f);

    $t.val($(this).text());
    $advSearch_popup.hide();

    return false;
  });

  /* initial trigger to populate empty fields */
  //$("#advSearch_year").change();
});


/* best offers scroll-load */
$(function() {
  var $panel = $("#introShelf");
  if ($panel.length == 0)
    return;

  var animationLock = 0;
  var $entry_template = $panel.find(".bestOffers li:first").clone();
  var xdata = null;

  $panel.find("a.next").click(function() {
    if (animationLock > 0) {
      console.warn("highlights: couldn't start next animation, locked");
      return false;
    }

    var offset = parseInt($(this).attr("href").split(",")[1]);

    var $page = $panel.find(".bestOffers:first");

    $page.wrap("<div />");
    var $placeHolder = $page.parent();

    $placeHolder.css({
      height: $page.outerHeight() + "px",
      overflow: "hidden"
    });

    animationLock = 2;

    function show_new_panel() {
      console.debug("best offers: showing the newly loaded page");

      var $new_page = null;

      $new_page = $("<ul />");

      /* build the new panel items */
      for (var i = 0; i < xdata.length; i++) {
        $entry = $entry_template.clone();
        $entry.find("img").attr("src", xdata[i].image);
        /* this updates two anchors, the image and the title */
        $entry.find("a").attr("href", xdata[i].url);
        /* this updates only the text title */
        $entry.children("h4").children("a").text(xdata[i].title);
        $entry.children(".price").html(xdata[i].price + " &euro;");
        $new_page.append($entry);
      }

      if (xdata.length < 4)
        offset = 0;
      else
        offset += 4;

      $panel.find("a.next").attr("href", "#next," + offset);

      /* wrap it in the proper div */
      $new_page.wrap("<div class=\"bestOffers\" />");
      $new_page = $new_page.parent();
      $new_page.css({ display: "none" });
      $new_page.append("<div class=\"clear\" />");

      $new_page.appendTo($placeHolder);
      $new_page.fadeIn(function() {
        $new_page.unwrap();
      });
    }

    /* start sliding animation for the older stuff */
    $page.hide("slide", { direction: "left" }, 400, function() {
      console.debug("best offers: sliding animation completed");
      animationLock--;

      /* purge the older page and everything associated with it, forever */
      $page.remove();

      /* if we the animation took longer than the ajax loading, proceed to
       * show the results, otherwise show a loading animation icon */
      if (animationLock == 0)
        show_new_panel();
      else
        $placeHolder.addClass("ajaxLoading");
    });

    /* start the ajax request */    
    $.getJSON("/", { ws: offset }, function(data) {
      console.debug("best offers: ajax loading completed");
      animationLock--;

      xdata = data;

      /* in case the animation was done before the loading completed, they
       * turned on the loading icon, which we can take off here */
      $placeHolder.removeClass("ajaxLoading");

      if (animationLock == 0)
        show_new_panel();

    }, "json");

    return false;
  });
});

