// Copyright 2007-2008 Gilt Groupe, Inc.
var fl;
if (!fl) {
    fl = {};
}
var Gilt;
if (!Gilt) {
  Gilt = {};
}

fl.Init = {};
fl.Init.is_initialized = false;
fl.Init.scms_version_id = null;
fl.Init.question_mark_regexp = null;
fl.Init.ImageUri = function(uri) { // why?
    return uri;
};

fl.Init.SetupImageUri = function(cdnUri, versionKey) {
    if (!fl.Init.question_mark_regexp) {
        fl.Init.question_mark_regexp = new RegExp(/\?j_/);
    }

    if (cdnUri) {
        fl.Init.ImageUri = function(uri) {
            if ( fl.Init.question_mark_regexp.test(cdnUri) )  {
                return cdnUri;
            }
            return cdnUri + uri + '?j_' + versionKey;
        };
    } else if (versionKey) {
        fl.Init.ImageUri = function(uri) {
            if ( fl.Init.question_mark_regexp.test(cdnUri) )  {
                return uri;
            }
            return uri + '?j_' + versionKey;
        };
    }
};

// cdnUri: The full path to the domain hosting our images (e.g. http://cdn.gilt.com)
// versionKey: Appended to every cdn image query via javascript. This should be the
//    most recent mtime of ALL assets we may serve from the CDN
fl.Init.WindowLoad = function(cdnUri, versionKey, scmsVersionId) {
    log.setup("startup", "fl")("Loading...");
    fl.Init.scms_version_id = scmsVersionId;

    fl.Init.SetupImageUri(cdnUri, versionKey);

    fl.Init.Initialize();
    fl.Init.is_initialized = true;
    log.stopAll();
};
// Can be called multiple times per page if the page uses ajax. For
// example, a form brought in via ajax will need to make sure this
// function is called to setup all of our validation on the form.
// This function should not have any parameters.
fl.Init.Initialize = function() {
    log.setup("startup", "fl")("Initializing Gilt Groupe");
    gg.Usermeta.init();
    gg.throttleFormSubmit();
    fl.ImageSubmit.init();
    fl.ImageRollover.init();
    fl.ToolTip.init();
    fl.Form.init();
    fl.Form.autoFocusForms();
    if (!gg.Admin.isAdminPage()) {
        // On admin, let rails validate forms.
        fl.Validate.AutoInit();
    }
    gg.Sprite.init();
    gg.processLoginKey();
    gg.FlashMessage.init();
    Gilt.SingleSignOnLinks.init();
    log("Initialization Complete").stop();
};
fl.Init.isInitialized = function() {
    return fl.Init.is_initialized;
};

fl.ImageSubmit = {};
// Looks for input type=image and downloads the images. We do this to
// get these particular images to download as quickly as possible
fl.ImageSubmit.init = function() {
    log.setup("startup", "fl")("Initializing Image Submit");
    var inputs = $('input[type=image]');
    var i = inputs.length;
    var el;
    while (el = inputs[--i]) {
        if (fl.Util.isInitialized('ImageSubmitInit', el)) {
            continue;
        }
        log.setup("startup", "fl")("Preloading %s", el.attr("src"));
        (new Image()).src = el.attr("src");
    }
    log("Image Submit Initialization Complete");
};
fl.ImageRollover = {};
fl.ImageRollover.useZoomEffect = true;
fl.ImageRollover.init = function() {
    log.setup("startup")("Initializing Image Rollovers");

    $("img[rollover]").rollover({
        rollover_source: "rollover",
        otherrollover_sources: "rollover_associated_ids",
        otherrollover_targets: "rollover_associated_urls"
    });

    var imgs = $(".zoom img");
    var i = imgs.length;
    while (i--) {
        imgs.eq(i).attr("fullsrc", imgs.eq(i).attr("src").replace(/\/sm\./,"/lg."));
    }
    if (fl.ImageRollover.useZoomEffect) {
      imgs.zoom({
        container: $("#photoZoom"),
        triggerEvent: "zoomstart", // custom event, so we can do some other stuff first
        useZoomInEffect: false,
        useZoomOutEffect: false,
        panSpeed: 0,
        easing: "linear"
        // All options, for demo:
        /*easing: (-1 != document.location.search.search(/[&\?]paneasing=(\w*)/)) ? document.location.search.match(/[&\?]paneasing=(\w*)/)[1] : "swing",
        panSpeed: (-1 != document.location.search.search(/[&\?]panspeed=(\d*|\w*)/)) ? parseInt(document.location.search.match(/[&\?]panspeed=(\d*)/)[1])||document.location.search.match(/[&\?]panspeed=(\w*)/)[1] : "fast",
        zoomSpeed: (-1 != document.location.search.search(/[&\?]zoominspeed=(\d*|\w*)/)) ? parseInt(document.location.search.match(/[&\?]zoominspeed=(\d*)/)[1])||document.location.search.match(/[&\?]zoominspeed=(\w*)/)[1] : "slow",
        resetSpeed: (-1 != document.location.search.search(/[&\?]zoomoutspeed=(\d*|\w*)/)) ? parseInt(document.location.search.match(/[&\?]zoomoutspeed=(\d*)/)[1])||document.location.search.match(/[&\?]zoomoutspeed=(\w*)/)[1] : "fast",
        useZoomInEffect: -1 == document.location.search.search(/[&\?]zoomin=(false)/),
        useZoomOutEffect: -1 == document.location.search.search(/[&\?]zoomout=(false)/)*/
      });
    }

    log("Image Rollover Initialization Complete");
};

fl.Form = {};
// Places focus on first non empty input field
// $(function() { fl.Form.focusFirstEmptyField('loginform'); });
fl.Form.focusFirstEmptyField = function(formId) {
    var input = $("#" + formId + " input:not(:hidden):blank:first");
    if (input.length) {
        input.focus();
    } else {
        $("#" + formId + " input:not(:hidden):first").focus();
    }
};
fl.Form.initChangeButtonOnSubmit = function() {
    log.setup("startup", "form")("Initializing Change Button On Submit Event");

    var forms = $(".autoChange:input:image").closest("form");

    if (forms.length) {
        $("<img/>").attr("src", '/images/default/buttons/please_wait.gif'); // TODO: this should be a constant
        var f = function() {
            log.setup("interaction", "form")("Changing Button on Submit");
            var img = $(this).find(".autoChange:image"); // I'm assuming there's only 1
            img.data("oldSrc", img.attr("src"))
               .attr("src", '/images/default/buttons/please_wait.gif');
            this.disable();
        };
        forms.unbind("submit", f).submit(f);
    }
};
fl.Form.enable = function() {
    var inputs = $('.autoChange:image');
    var i = inputs.length;
    if (i) {
        while (--i) {
            var el = inputs.eq(i);
            if (el.data("oldSrc")) {
                el.attr("src", el.data("oldSrc"))
                  .removeData("oldSrc")
                  .closest("form")
                    .get().enable();
            }
        }
    }
};
// To focus first input element of a form:
// <% form_tag url_for(:action =>  'update'), :class => 'autoFocus' do -%>
// To focus first empty input element of a form:
// <% form_tag url_for(:action =>  'update'), :class => 'autoFocusEmpty' do -%>
fl.Form.autoFocusForms = function() {
    log.setup("startup", "fl", "form")("Autofocusing on Form");
    var forms = $('form');
    var i = -1;
    var max = forms.length;
    while (++i < max) {
        var el = forms.eq(i);
        if (el.hasClass('autoFocus')) {
            log("Focusing on first field");
            el.find("input[type!=hidden]:first").focus();
            return;
        } else if (el.hasClass('autoFocusEmpty')) {
            log("Focusing on first empty field");
            fl.Util.MaybeAssignID(el);
            fl.Form.focusFirstEmptyField(el.id());
            return;
        }
    }
};
// Auto disable the submit button until all inputs have data.
// If you do not pass in the ID of the submit tag, we'll disable the
// first one we find in the form (first image or submit input tag)
// $(function() { fl.Form.autoDisableSubmit('loginform', 'submit'); });
fl.Form.autoDisableSubmit = function(formId, submitId) {
    log.setup("startup", "fl", "form")("Disabling form submit for form #%s", formId);
    if (!submitId) {
        var form = $("#" + formId);
        if (!form) {
            return;
        }
        var el = form.find(":image, :submit").eq(0);
        if (!el.id()){
            el.id('_fl_autoDisableSubmit');
        }
        submitId = el.id();
    }

    fl.Form.autoDisableSubmitCheck(formId, submitId);
    var inputs = $("#" + formId + " :input");
    var i = inputs.length;
    var f = function() {
        fl.Form.autoDisableSubmitCheck(formId, submitId);
    };
    while (i--) {
        inputs.eq(i).blur(f);
    }

    // Also observe the form so you don't have to tab out of a final text box
    log("Attaching a Form Observer");
    /*new Form.Observer(formId, 0.5, function(_, value) { // TODO: jquery equivalent, probably a plugin
        var map = value.toQueryParams();
        var filled_out = true;
        for (var key in map) {
            if (map.hasOwnProperty(key) && !map[key]) {
                filled_out = false;
                return;
            }
        }
        if (filled_out) {
            fl.Form.autoDisableSubmitCheck(formId, submitId);
        }
    });*/
};
fl.Form.autoDisableSubmitCheck = function(formId, submitId) {
    log.setup("interaction", "fl", "form")("Checking for missing data");
    var inputs = $("#" + formId + " :input");
    var i = inputs.length;
    while (i--) {
        if (!inputs.eq(i).val()) {
            log("Missing data found, disabling submit");
            $("#" + submitId).attr("disabled","disabled");
            return;
        }
    }
    log("No missing data found, enabling submit");
    $("#" + submitId).attr("disabled","");
};
fl.Form.init = function() {
    log.setup("startup", "fl", "form")("Initializing Forms");
    fl.Form.initPreviewText();
    fl.Form.initChangeButtonOnSubmit();
    fl.Form.initOnKeyPress();
    fl.Form.initPhoneNumberFields();
    fl.Form.usermetaPrefillEmail();
    log("Forms Initialization Complete");
};

fl.Form.initPhoneNumberFields = function() {
    log.setup("startup", "fl", "form")("Adding Phone Number Formatters");
    var inputs = $('input[type=text]');
    var i = inputs.length;
    var el;
    var f = function(el) {
        return function() {
            fl.Formatter.phone(el);
        };
    };
    while (--i > -1) {
        el = inputs.eq(i);
        if (el.hasClass('phone_number')) {
            fl.Formatter.phone(el);
            el.blur(f(el));
        }
    }
};

// looks for test field inputs with class user_prefill_email, and
// prefills the box with the contents from a cookie named email, if set
fl.Form.usermetaPrefillEmail = function() {
    if (-1 != window.location.toString().indexOf('noemail=')) {
        return;
    }

    var cookie_value = fl.Util.readCookie('email');
    if (!cookie_value) {
        return;
    }
    log.setup("startup", "fl", "form")("Adding detected email address %s to all email fields", cookie_value);
    if (!$("input.usermeta_prefill_email[type=text]").val()) {
        $("input.usermeta_prefill_email[type=text]").val(cookie_value);
    }
};

// Submits the form that contains the specified link. Handles ajax and
// traditional submits
fl.Form.submit_link = function(linkElement) {
    fl.Form.submit_form($(linkElement).closest("form"));
};
fl.Form.submit_form = function(form) {
    form = $(form);
    if (form[0] && form[0].onsubmit) {
        // this triggers if the html has an onsubmit="", eg form comes from rails' form_remote_tag().
        form[0].onsubmit();
    } else {
        // this triggers if the onsubmit handlers are set in jquery.
        form.submit();
    }
};
// Now that we're using links for submit buttons, we need to manually trap the enter key
// to submit forms that do not otherwise have submit buttons
// Key code 40 is the down arrow. 38 is the up arrow. If the previous
// key code is one of these, do not submit the form - the user is
// selecting from a list (e.g. an autocompleted list)
fl.Form.lastKeyCode = null;
fl.Form.initOnKeyPress = function() {
    log.setup("startup", "form")("Initializing Form KeyPress Handlers");
    $("form:not(:has(:submit))").keypress(function(event){
        if (13 == event.keyCode && 38 != fl.Form.lastKeyCode && 40 != fl.Form.lastKeyCode){
            log.setup("interaction", "form")("Detected Enter key without immediately prior up or down key, submitting form");
            fl.Form.submit_form($(this).closest("form"));
        }
        fl.Form.lastKeyCode = event.keyCode;
    });
    $(":input:not(textarea,select,:hidden)").keypress(function(event){
        if (13 == event.keyCode && 38 != fl.Form.lastKeyCode && 40 != fl.Form.lastKeyCode){
            log.setup("interaction", "form")("Detected Enter key without immediately prior up or down key, submitting form");
            fl.Form.submit_form($(this).closest("form"));
        }
        fl.Form.lastKeyCode = event.keyCode;
    });
};
// Allows you to set defaults in text fields for any form elements on the page
// text_field_tag this_field, nil, { :preview_text => 'friend@email.com' }
fl.Form.initPreviewText = function() {
    $(":input[preview_text]").coolinput({ source: 'preview_text', blurClass: 'form_preview_text' });
};

// Creates a simple, lightweight tooltip that displays immediately
// below the text the mouse is pointing to. Unobtrusive:
// <dl class="static_tooltip">
//  <dt>Text 2</dt>
//  <dd>Tip 2</dd>
// </dl>
fl.ToolTip = {};
fl.ToolTip.init = function() {
    log.setup("startup", "tooltip")("Initializing Tooltips");

    $("dl.static_tooltip").each(function() {
        if ($(this).data('qtip')) return; // Skip lists which already have an initialized qtip object

        var el = $(this);
        var corner = { target: 'leftMiddle', tooltip: 'rightTop' };
        var tipCorner = "rightTop";
        if (el.closest("#sql_trace").length) {
            corner = { target: 'rightMiddle', tooltip: 'leftTop' };
            tipCorner = "leftTop";
        }
        var style = {
            name: "red",
            color: 'black',
            border: { width: 1 },
            fontSize: '11px',
            lineHeight: '130%',
            tip: {
                corner: tipCorner,
                size: { x: 12, y: 12 }
            }
        };
        if (!el.parent(".field_info")) {
            style.width = { max: 800 };
        }
        el.qtip({
            content: el.find("dd").html(),
            position: {
                target: el.find("dt"),
                corner: corner
            },
            show: {
                effect: {
                    type: 'slide',
                    length: 400
                }
            },
            hide: {
                fixed: true,
                effect: {
                    type: 'slide',
                    length: 200
                }
            },
            style: style
        });
    });
    log("Tooltip Initialization Complete");
};

fl.Validate = {}; // (mostly) DEPRECATED, replaced by validation plugin

// Returns true if the specified string is an integer
fl.Validate.IsInteger = function (str) { // Used by Credit Card Formatter -- Do not delete (yet)
    var i = -1;
    var max = str.length;
    while (++i < max) {
        var c = str.charCodeAt(i);
        if (57 < c || 48 > c){
            return false;
        }
    }
    return true;
};
fl.Validate.AutoInit = function() {
    log.setup("startup", "fl", "validate")("Initializing Form Validation");

    $("form").each(function() {
        $(this).validate({
            //debug: true, // enable to disable form submission, + some debug statements in validate plugin
            errorPlacement: function(error, element) { // TODO: test this placement thoroughly
                //error.css({ display: 'inline', 'float': 'none', margin: 0, width: 'auto' }); // reset some styles.  label.error styles isn't working, it's being applied before some other styles, and being overwritten
                var insertion_point = element.endOfLine(); // place error message after end of current line.
                insertion_point.after(error);
                if (error.offset().top < element.offset().top + element.height()) { // if the line had some space at the end, the error might not go onto a new line.
                    insertion_point.after("<br/>");
                }
            },
          highlight: function(element, errorClass, validClass ) {
            $(element).addClass(errorClass).removeClass(validClass);
            var selectmenu = $(element).data("selectmenu");
            if (selectmenu) {
              selectmenu.newelement.addClass("ui-state-error").removeClass(validClass);
            }
          },
          unhighlight: function( element, errorClass, validClass ) {
            $(element).removeClass(errorClass).addClass(validClass);
            var selectmenu = $(element).data("selectmenu");
            if (selectmenu) {
              selectmenu.newelement.removeClass("ui-state-error").addClass(validClass);
            }
          }
        });
    });
};
// In RJS: page << "fl.Validate.addFormError('addform', '#{error_messages_for(:brand)}');"
// Automatically adds a div tag to contain the error messages for this form if needed.
fl.Validate.addFormError = function(divId, errorMessages) {
    var el = $("#" + divId);
    var errorId = divId + "-E";
    var items = $('#' + errorId);
    var fullMessage = '<div id="' + errorId + '">' + errorMessages + '</div>';
    if (!items.length) {
        el.prepend(fullMessage);
    } else {
        items.html(fullMessage);
    }
};

fl.Validate.hideAllErrors = function() {
    $('.errorExplanation, label.error').hide();
};

fl.Refresh = {};
fl.Refresh.count = null;
fl.Refresh.set_message = function(statusId, message) {
    var el = $("#" + statusId);
    if (el.html() != message) {
        el.html(message);
    }
};
fl.Refresh.auto_refresh = function(statusId, interval, url) {
    fl.Refresh.countdown(statusId, interval, function() { // TODO: not the best way to do this
        window.location = url;
    });
};

// Used to update a div automatically with a countdown timer (e.g. 10
// seconds, 9 seconds, etc.). Callback, if provided, is invoked when 0
// is reached.
fl.Refresh.countdown = function(statusId, interval, callback) {
    if (!fl.Refresh.count) {
        fl.Refresh.count = {};
    }
    var count = (fl.Refresh.count[statusId] || 0) + 1;
    fl.Refresh.count[statusId] = count;

    var elapsed = (count / 4);
    var number_seconds = interval - elapsed;

    var minutes = parseInt(number_seconds / 60);
    var seconds = parseInt(number_seconds % 60).toString();
    if (1 == seconds.length){
        seconds = "0" + seconds;
    }

    fl.Refresh.set_message(statusId, minutes + ":" + seconds + "" + Locale.minutes);
    if (elapsed >= interval) {
        fl.Refresh.count[statusId] = null;
        if (callback) {
            callback();
        }
        return;
    }
    setTimeout(function() {
        fl.Refresh.countdown(statusId, interval, callback);
    }, 250);
};


