/**
* AJAX/JSON Methods
*
* @todo WRITE IN JSON STRINGIFYER/DOWNLOAD ONE FOR CHRISTSCH SAKE JOE
*
* This class is instantiated here and made globally-available, however, the main
* wrapper object (Setup) will refer to and rely on this being available.
*/

// Also, YAY for JsLint validation. Read this shit: http://javascript.crockford.com/code.html it's important!!


// Globals -- NOTE: DO NOT RE-DECLARE $, jQuery, window, document, etc. EVEN IF JSLint hurts your feelings about it :) What a Crockford.
/*global $, window, document, alert, confirm */

// It would be VERY NICE to be able to declare static variables in JS
window.ContentSelector = {};
window.categoryCount = 0;
window.pageSectionCount = 0;


// @public prototypeable class Ajx{}
function Ajx() {

  var $Box = {}, box = [], $Clone = {}, $ContentCover = {}, $Loading = {}, $Target = {}, target = [], winProps = [];


/* ______________________________ routine ajax functions ______________________________ */

  // @privileged anonymous
  this.show = function (targetId, href, animationType) {

    $Target = $("#" + targetId);
    $Target.removeClass("hidden");

    if ($Target !== undefined && $Target.hasClass("ajaxCloneable")) {
      $Clone = $Target.clone();
      $Target.after($Clone);

      $Target = $Clone;
      $Clone = {};

      $Target.removeClass("ajaxCloneable");
    }

    $Loading = $("#loadingCover");

    if ($Loading !== undefined) {
      $Loading = $Loading.clone();
    }

    target.height = $Target.height();
    target.cssHeight = $Target.css("height");

    if (target.height === undefined || target.height < 50) {
      $Target.addClass("loading_height");
    }

    $Target.empty();
    $Target.prepend($Loading);
    $Loading.show();

    if (animationType === 'slideDown') {
      $Target.slideDown("fast");
    } else {
      $Target.show();
    }

    $.ajax({
      type: 'GET',
      url: href,
      success: function (data) {
        $Target.removeClass("loading_height");
        $Target.empty();

        if ($Target.hasClass("ajaxAppend")) {
          $Target.append(data);
          $Target.removeClass("ajaxAppend");
        } else {
          $Target.prepend(data);
        }

        $("a[class^='button']").addClass("button_color");

        if (animationType === 'slideDown') {
          $Target.fadeIn("normal");
        }
      }
    });

    return false;
  }; // End show()

  // @privileged anonymous
  this.windowProperties = function () {

    winProps.windowWidth = $(window).width();
    winProps.windowHeight = $(window).height();
    winProps.pageHeight = $(document).height();
    winProps.pageScroll = $(window).scrollTop();

    return winProps;
  }; // End windowProperties()

  // @privileged anonymous
  this.centerElement = function (elementId, currentWinProps) {

    currentWinProps = this.windowProperties();

    $Box = $("#" + elementId);
    box = [];
    box.width = $Box.width();
    box.height = $Box.height();

    $Box.css("left", (((currentWinProps.windowWidth * 0.50) - (box.width * 0.50)) - 18) + 'px');
    $Box.css("top", ((currentWinProps.windowHeight * 0.50) - (box.height * 0.50) + currentWinProps.pageScroll) + 'px');

    $Box.show();
  }; // End centerElement()

  // @privileged anonymous
  this.presentLoading = function (type, boxId) {

    $Box = $("#" + boxId);

    if (type === 'layer') {
      $Loading = $("#loadingStationary");

      $Loading.css("width", $Box.outerWidth());
      $Loading.css("height", $Box.outerHeight());

      box.offset = $Box.offset();
      $Loading.css("left", box.offset.left);
      $Loading.css("top", box.offset.top);

      $Loading.fadeIn('fast');
    } else {
      $Loading = $("#loadingCover").clone();

      $Box.empty();
      $Box.prepend($Loading);
      $Loading.show();
    }

    return false;
  }; // End presentLoading()

  // @privileged anonymous
  this.hideLoading = function (type) {

    if (type === 'layer') {
      $("#loadingStationary").fadeOut("fast");
    } else {
      $("#loadingCover").remove();
    }

    $("a[class^='button']").addClass("button_color");

    return false;
  }; // End hideLoading()

  // @privileged anonymous
  this.presentCover = function (winProps) {

    $ContentCover = $("#contentCover");

    $ContentCover.css("width", winProps.windowWidth + 'px');
    $ContentCover.css("height", winProps.pageHeight + 'px');

    $ContentCover.show();

    return false;
  }; // End presentCover()

  // @privileged anonymous
  this.hideCover = function () {

    $ContentCover = $("#contentCover");
    $ContentCover.hide();

    return false;
  }; // End hideCover()

  return;
} // End class Ajx{}

window.Ajx = new Ajx();


// @public prototypeable class Setup{}
function Setup() {

  var $Delegate = {}, $PageSections = {}, $PageSectionInputs = {}, $PageSectionTypeInputs = {}, pageSectionTypeKey = null, pageSectionTypeValue = null, pageSectionAccessorId = null, JsonData = {}, $PageSectionTypeAccessor = {}, pageSectionTypeAccessorId = null, toggleBlockSelector = null, $Closeable = {}, $ContentArea = {}, selectorId = null, $Actionable = {}, removable = null, $Form = {}, $Loading = {}, redirectTo = null, cancelRedirect = null, changedHeight = false, mediaFormTarget = null, $MediaForm = {}, $MediaContentArea = {}, $MediaLoading = {}, $NewInput = {}, $Box = {}, box = [], cacheType = null, winProps = [], $PreviewPane = {}, previewHeight = null, formTarget = null, alternateActionable = null, sectionCount = 0;


/* Begin object delegation. yay jQuery you da man */

  // @privileged anonymous
  this.commence = function () {

/* _________________ add category to form actionable [delegation] ________________________ */

    $("#articleSettings").delegate("a[href$='#add']", "click", function () {

      $Delegate = $(this);

      $(".categorySelect:last").after($(".categorySelect:last").clone());

      if (window.categoryCount === 0) {
        $(".categorySelect:last").append('&nbsp; <a href="#remove">remove</a><br />');
      }
      window.categoryCount = window.categoryCount + 1;

      $(".categorySelect:last select").attr("name", "data[Article][ObjectAssociation][Category][" + window.categoryCount + "]");
      $(".categorySelect:last select").attr("id", "ArticleObjectAssociationCategory" + window.categoryCount);

      $(".categorySelect").delegate("a[href$='#remove']", "click", function () {
        window.categoryCount = window.categoryCount - 1;
        $Delegate.parent('.categorySelect').remove();

        return false;
      });

      return false;
    }); // End category delegation


/* _________________ remove newly added section from page/page template actionable [delegation] _____________ */

    $("#pageTemplateSections").delegate("a[href$='#remove']", "click", function () {

      $Delegate = $(this);

      $Delegate.parent('.pageSectionInput').remove();

      if (window.pageSectionCount > 0) {
        window.pageSectionCount = window.pageSectionCount - 1;
      }

      /* The other sections need their ID numbers rearranged from zero up */
      $PageSectionInputs = $("#newPageSections > .pageSectionInput");
      $.each($PageSectionInputs, function (key, parentElement) {
        $(parentElement).children("input").attr("name", "data[Page][ObjectAssociation][PageSection][page_section_name][" + key + "]");
        $(parentElement).children("input").attr("id", "PageObjectAssociationPageSectionPageSectionName" + key);
      });

      return false;
    });


/* __________________ autosave for checkboxes in page sections form _____________________________ */

    $(".pageSectionInput").delegate(":checkbox", "click", function () {

      $Delegate = $(this);

      // JSON-ify the checkbox's field name as a collection key in the Secondary Object PageSectionType
      pageSectionTypeKey = $Delegate.attr("name");
      // Get the new value of the checkbox
      pageSectionTypeValue = $Delegate.attr("checked");

      if (pageSectionTypeValue === 'checked' || pageSectionTypeValue === 'on' || pageSectionTypeValue === 1 || pageSectionTypeValue === true) {
        pageSectionTypeValue = 1;
      } else {
        pageSectionTypeValue = 0;
      }

      // Get the Accessor ID of the Page Section (for saving data to the PageSections Widget)
      pageSectionAccessorId = $Delegate.closest("span").prevAll("input[name='page_section_accessor']").attr("value");

      JsonData = {
        "data" : {
          "WidgetAlias" : "PageSections",
          "PageSections" : {
            "Accessor" : {
              "id" : pageSectionAccessorId
            }
          },
          "PageSection" : {
            "page_section_active" : 1
          },
          "PageSectionType" : {}
        }
      };

      // For some reason, the JSON object won't accept variables as keys. It is a language "feature" so they say (to require strings as keys)..
      JsonData.data.PageSectionType[pageSectionTypeKey] = pageSectionTypeValue;

      // Attempt to find an existing association from an already-existent PageSectionType > PageSection
      $PageSectionTypeAccessor = $Delegate.closest("span").prevAll("input[name='page_section_type_accessor']");

      if ($PageSectionTypeAccessor !== undefined) {
        // The Accessor ID must be known when updating existing data
        pageSectionTypeAccessorId = $PageSectionTypeAccessor.attr("value");
        JsonData.data.PageSectionType.Accessor = { "id" : pageSectionTypeAccessorId };
      }

      $.ajax({
        type: 'POST',
        url: '/admin/ajax/page_sections/save/save',
        data: JsonData,
        success: function (data) {
          /*$("#drinkMe").html(data);*/
          return;
        }
      });
    }); // End page type autosave delegation

    
/* _________________________ hide modal actionable [delegation] __________________________ */

    $(".layer").delegate("a[href$='#close']", "click", function () {

      $Delegate = $(this);

      $("#contentCover").hide();
      $Delegate.parent().hide();

      return false;
    }); // End modal close delegation


/* _________________________ show/get ajax/static content [delegation] __________________________ */

    $("body").delegate(".ajaxShow", "click", function () {

      $Delegate = $(this);

      toggleBlockSelector = $Delegate.attr("title");

      if (toggleBlockSelector !== undefined && toggleBlockSelector !== '' && toggleBlockSelector !== null) {
        $("#" + toggleBlockSelector).toggle();
      }

      Ajx.show($Delegate.attr("rel"), $Delegate.attr("href"), 'slideDown');

      return false;
    }); // End modal (ajax only) show delegation


/* _________________________ hide ajax/static content [delegation] ______________________________ */

    $("body").delegate("a[href$='#ajaxHide']", "click", function () {

      $Delegate = $(this);

      $Closeable = $Delegate.closest(".ajaxCloseable");
      $Closeable.slideUp('fast');
      $Closeable.empty();

      return false;
    }); // End modal (ajax or static) close delegation


/* ________________________ toggle static content (no ajax) [delegation] ___________________________ */

    $("body").delegate("a[href$='#toggle']", "click", function () {

      $Delegate = $(this);

      toggleBlockSelector = $Delegate.attr("rel");

      if (toggleBlockSelector !== undefined && toggleBlockSelector !== '' && toggleBlockSelector !== null) {
        $("#" + toggleBlockSelector).toggle();
      }

      return false;
    }); // End modal (static only) toggle delegation


/* ________________ hide & remove ajax from absolutely positioned content [delegation] ___________ */

    $("body").delegate("a[href$='#ajaxHideStationary']", "click", function () {

      $Delegate = $(this);

      $ContentArea = $Delegate.closest(".contentArea");
      $Closeable = $Delegate.closest(".ajaxCloseable");

      $Closeable.hide();
      Ajx.hideCover();
      $ContentArea.empty();

      return false;
    }); // End hide fixed modal (ajax only) delegation


/* ________________________ submit (POST) actionable [delegation] __________________________ */

    $("body").delegate("a[href$='#submit']", "click", function () {

      $Delegate = $(this);

      $Form = $Delegate.closest("form");
      selectorId = $Delegate.attr("rel");

      $Actionable = $("#" + selectorId);
      removable = $Actionable.attr("rel");

      Ajx.presentLoading('layer', selectorId);

      $.ajax({
        type: 'POST',
        url: $Form.attr("action"),
        data: $Form.serialize(),
        success: function (data) {
          if (removable === 'removable') {
            Ajx.hideLoading('layer');

            $Actionable.fadeOut("medium", function () {
              $Actionable.remove();
            });
          } else {
            $Actionable.empty();
            $Actionable.prepend(data);

            Ajx.hideLoading('layer');
          }

          return false;
        }
      });

      return false;
    }); // End submit actionable delegation


/* _________________________ save (POST) actionable [delegation] ______________________________ */

    $("body").delegate("a[href$='#save']", "click", function () {

      $Delegate = $(this);

      formTarget = $Delegate.attr("rev");

      if (formTarget !== undefined && formTarget !== '' && formTarget !== null) {
        $Form = $("#" + formTarget);
      } else {
        $Form = $Delegate.closest("form");
      }

      $ContentArea = $Form.find(".contentArea");
      redirectTo = $Form.attr("rel");
      // These hacks are completely arbitrary so that the project can move forward. REMOVE THEM AND STANDARDIZE rel, rev, title, etc.
      cancelRedirect = $Delegate.attr("rel");

      if ($ContentArea.length === 0) {
        selectorId = $Delegate.attr("title");
        $Actionable = $("#" + selectorId);

        Ajx.presentLoading('layer', selectorId);
      } else {
        // ContentSelector is global :( (is there a way to store a public or even private variable that retains its reference in JS????)
        window.ContentSelector = $ContentArea;
        $Loading = $("#loadingCover").clone();

        $ContentArea.empty();
        if ($ContentArea.css('height') === 'auto' || $ContentArea.css('height') === '0px') {
          $ContentArea.css('height', '25px');
          changedHeight = true;
        }

        $ContentArea.prepend($Loading);
        $Loading.show();
        $ContentArea.show();
      } // End if/else

      if ($Form.has("iframe").length === 1) {
        $Form.submit();
      } else {
        $.ajax({
          type: 'POST',
          url: $Form.attr("action"),
          data: $Form.serialize(),
          success: function (data) {
            if (redirectTo !== undefined && redirectTo !== '' && redirectTo !== null && cancelRedirect !== 'stay') {
              window.location = redirectTo;
            } else if ($ContentArea.length === 0) {
              Ajx.hideLoading('layer');
            } else {
              if (changedHeight) {
                $ContentArea.css('height', 'auto');
              }

              $ContentArea.empty();
              $ContentArea.prepend(data);
            } // End if/else

            return false;
          } // End success
        });
      } // End if/else

      return false;
    }); // End save actionable delegation


/* _________________________ save queue item actionable [delegation] ______________________________ */

    $("body").delegate("a[href$='#saveQueueItem']", "click", function () {

      $Delegate = $(this);

      $Form = $Delegate.closest("form");
      mediaFormTarget = $Delegate.attr("rev");
      $MediaForm = $("#" + mediaFormTarget);

      $ContentArea = $Form.find(".contentArea");
      $MediaContentArea = $MediaForm.find(".contentArea");

      window.ContentSelector = $MediaContentArea;
      $Loading = $("#loadingCover").clone();
      $MediaLoading = $("#loadingCover").clone();

      $ContentArea.css('height', '25px');
      $ContentArea.empty();
      $ContentArea.prepend($Loading);
      $Loading.show();
      $ContentArea.show();

      $MediaContentArea.css('height', '25px');
      $MediaContentArea.empty();
      $MediaContentArea.prepend($MediaLoading);
      $MediaLoading.show();
      $MediaContentArea.show();

      // First, POST the Queue data, then send the image to the dummy AJAX iFrame. It will in turn submit the hidden trixy-smiegel (TRIP STACK)
      $.ajax({
        type: 'POST',
        url: $Form.attr("action"),
        data: $Form.serialize(),
        success: function (data) {
          $ContentArea.css('height', 'auto');
          $ContentArea.empty();
          $ContentArea.prepend(data);

          // Submits the image to the dummy ajax iframe
          $MediaForm.submit();

          return false;
        }
      });

      return false;
    }); // End save queue item actionable delegation


/* _________________________ delete actionable [delegation] ______________________________ */
    
    $("body").delegate("a[href$='#delete']", "click", function () {

      $Delegate = $(this);
      $Actionable = null;

      selectorId = $Delegate.attr("rel");
      $Form = $("#" + selectorId);
      redirectTo = $Form.attr("rel");
      alternateActionable = $Delegate.attr("rev");

      $ContentArea = $Form.find(".contentArea");

      if (alternateActionable !== null && alternateActionable !== '' && alternateActionable !== undefined) {
        selectorId = alternateActionable;
        $Actionable = $("#" + selectorId);

        Ajx.presentLoading('layer', selectorId);
      } else if ($ContentArea.length === 0) {
        selectorId = $Delegate.attr("title");
        $Actionable = $("#" + selectorId);

        Ajx.presentLoading('layer', selectorId);
      } else {
        $Loading = $("#loadingCover").clone();
        $ContentArea.empty();

        box = [];
        box.oldHeight = $ContentArea.css("height");
        box.newHeight = box.oldHeight;

        if (box.oldHeight === 'auto' || box.oldHeight === '0px') {
          box.newHeight = '25px';
        }

        $ContentArea.css("height", box.newHeight);

        $ContentArea.prepend($Loading);
        $Loading.show();
        $ContentArea.show();
      } // End if/elseif/else

      /// @todo CHANGE THIS to modal dialog instead of browser dialog (if browser can support it)
      if (confirm("are you sure that you wish to delete this object? this action CANNOT be undone.")) {
        $.ajax({
          type: 'POST',
          url: $Form.attr("action"),
          data: $Form.serialize(),
          success: function (data) {
            if (redirectTo !== undefined && redirectTo !== '' && redirectTo !== null) {
              window.location = redirectTo;
            } else if ($ContentArea.length === 0 || $Actionable !== null) {
              Ajx.hideLoading('layer');

              $Actionable.fadeOut("medium", function () {
                $Actionable.remove();
              });
            } else {
              $ContentArea.css("height", box.oldHeight);
              $ContentArea.empty();
              $ContentArea.prepend(data);
            }

            return false;
          } // End success
        }); // End $.ajax()
      } else {
        if ($ContentArea.length === 0) {
          Ajx.hideLoading("layer");
        } else {
          $ContentArea.remove("#loadingCover");
        }
      } // End if/else

      return false;
    }); // End delete actionable delegation


/* ________________________ delete site cache delegation ________________________________ */

    $("#admin_header").delegate("a[href$='#clearCache']", "click", function () {

      $Delegate = $(this);
      cacheType = $Delegate.attr("title");

      Ajx.presentLoading("layer", "admin_header");

      JsonData = {
        "data" : {
          "ClearCache" : "true",
          "CacheType" : cacheType
        }
      };

      $.ajax({
        type: 'POST',
        url: '/admin/ajax/cache/clear',
        data: JsonData,
        success: function (data) {
          $Delegate.replaceWith('cache cleared');
          Ajx.hideLoading('layer');

          return false;
        }
      });

      return false;
    }); // End delete cache delegation


/* _________________________ media container event bindings ______________________________ */

    $("a[href$='#media']").click(function () {

      winProps = Ajx.windowProperties();
      Ajx.presentCover(winProps);

      $Box = $("#mediaAssetsBox");
      box = [];
      box.width = $("#admin_container").outerWidth() * 0.90;
      box.height = winProps.windowHeight * 0.75;

      $Box.css('width', box.width + 'px');
      $Box.css('height', box.height + 'px');
      $Box.css('left', (((winProps.windowWidth * 0.50) - (box.width * 0.50)) - 18) + 'px');
      $Box.css('top', ((winProps.windowHeight * 0.50) - (box.height * 0.50) + winProps.pageScroll) + 'px');

      $Box.show();

      return false;
    }); // End media container bind


/* ______________________ preview container event bindings ______________________________ */

    $("a[href$='#preview']").click(function () {

      $Delegate = $(this);

      winProps = Ajx.windowProperties();
      Ajx.presentCover(winProps);

      $Box = $("#previewBox");
      box = [];
      box.width = $("#admin_container").outerWidth() * 0.90;
      box.height = winProps.windowHeight * 0.75;

      $Box.css('width', box.width + 'px');
      $Box.css('height', box.height + 'px');
      $Box.css('left', (((winProps.windowWidth * 0.50) - (box.width * 0.50)) - 18) + 'px');
      $Box.css('top', ((winProps.windowHeight * 0.50) - (box.height * 0.50) + winProps.pageScroll) + 'px');

      $Box.show();

      $Form = $Delegate.closest("form");
      $PreviewPane = $("#previewPane");
      $Loading = $("#loadingCover").clone();

      $PreviewPane.empty();
      $PreviewPane.css("height", (box.height - 80) + 'px');
      $PreviewPane.prepend($Loading);
      $Loading.show();
      $PreviewPane.show();

      $.ajax({
        type: 'POST',
        url: $Delegate.attr("title"),
        data: $Form.serialize(),
        success: function (data) {
          $PreviewPane.fadeOut('fast', function () {
            $PreviewPane.empty();
            $PreviewPane.prepend(data);

            $("a[class^='button']").addClass("button_color");

            $PreviewPane.fadeIn('fast', function () {
              previewHeight = $("#previewContent").height();

              if (previewHeight > box.height) {
                $Box.css("height", (previewHeight + 160) + 'px');
              }
            });
          }); // End fadeout

          return false;
        } // End success
      }); // End ajax post

      return false;
    }); // End preview container bind


/* _________________________ create issue container event bindings ______________________________ */

    $("a[href$='#issue']").click(function () {

      $Delegate = $(this);

      winProps = Ajx.windowProperties();
      Ajx.presentCover(winProps);

      $Box = $("#issueBox");
      box = [];
      box.width = $Box.outerWidth();
      box.height = $Box.outerHeight();

      $Box.css('left', (((winProps.windowWidth * 0.50) - (box.width * 0.50)) - 18) + 'px');
      $Box.css('top', ((winProps.windowHeight * 0.50) - (box.height * 0.50) + winProps.pageScroll) + 'px');

      $Box.show();
      Ajx.show('issuePane', $Delegate.attr("title"));

      return false;
    }); // End issue delegation


/* ________________________ attach a neat color-changer-thing to buttons ________________ */

    // jQuery is so fucking raw
    $("a[class^='button']").live("mousedown mouseup", function (event) {

      $Delegate = $(this);

      if (event.type === "mousedown") {
        $Delegate.addClass("button_down_color");
        $Delegate.removeClass("button_color");
        $Delegate.removeClass("button_over_color");
      } else if (event.type === "mouseup") {
        $Delegate.addClass("button_color");
        $Delegate.removeClass("button_down_color");
      }
    });

    $("a[class^='button']").live("mouseover mouseout", function (event) {

      $Delegate = $(this);

      if (event.type === "mouseover") {
        $Delegate.addClass("button_over_color");
        $Delegate.removeClass("button_down_color");
        $Delegate.removeClass("button_color");
      } else if (event.type === "mouseout") {
        $Delegate.addClass("button_color");
        $Delegate.removeClass("button_down_color");
        $Delegate.removeClass("button_over_color");
      }
    });

    $("a[class^='button']").addClass("button_color");

    return;
  }; // END commence()

  return;
} // End class Setup{}

window.Setup = new Setup();

// Attach (and run when ready) Setup.commence() to make everything available appropriately by delegation
$(document).ready(Setup.commence);

// @public class Handler
function Handler() {

  // @privileged
  this.respond = function (actionForRequest, messages) {

    // messages MUST be JSON-encoded
    $.ajax({
      url: actionForRequest,
      data: messages,
      cache: false,
      success: function (result) {
        window.ContentSelector.html(result);
        window.ContentSelector.removeClass('loading');
      }
    });

    return false;
  }; // End @privileged respond()

  return;
} // End class Handler{}

// Make this object globally available
window.Handler = new Handler();
