var replaceClassName = function(node, sClassName, rClassName) {
    var n = jQuery(node);
    if (n.is('.'+sClassName)) {
        n.removeClass(sClassName);
        n.addClass(rClassName);
    }
};

var initOverLabels = function(node) {
    if (!node) {
        node = document;
    }
    // Set focus and blur handlers to hide and show
    // LABELs with 'overlabel' class names.
    var $labels = jQuery('label.overlabel[for]', node)
    var labelsLen = $labels.length;
    var i;
    for (i=0; i<labelsLen; i++) {
        var label = $labels[i];
        // Skip labels that do not have a named association
        // with another field.
        var id = label.htmlFor || label.getAttribute('for');
        var field = jQuery('#'+id);
        if (id && field) {
            // Change the applied class to hover the label
            // over the form field.
            replaceClassName(label, 'overlabel', 'overlabel-apply');

            // Hide any fields having an initial value.
            if (field.val() !== '') {
                hideLabel(id, true);
            }

            // Set handlers to show and hide labels.
            field.focus(function () {
                hideLabel(this.getAttribute('id'), true);
            });
            field.blur(function() {
                if (this.value === '') {
                    hideLabel(this.getAttribute('id'), false);
                }
            });

            // Handle clicks to LABEL elements (for Safari).
            jQuery(label).click(function() {
                var id, field;
                id = this.getAttribute('for');
                if (id && (field = jQuery('#'+id))) {
                    field[0].focus();
                }
            });
        }
    }
};

var hideLabel = function(field_id, hide) {
    var label = jQuery("label[for='"+field_id+"']");
    if (label) {
        label.css("textIndent", (hide) ? '-10000px' : '0px');
        return true;
    }
};

var toggle = function(ev) {
    if (!ev) {
        ev = window.event;
    }
    var elem = ev.target || ev.srcElement;
    // Let links pass
    if ((elem.nodeName.toLowerCase()=="input") || (elem.nodeName.toLowerCase()=="label") ||
        (elem.nodeName.toLowerCase()=="a" && elem.hasAttribute("href"))) {
        ev.cancelBubble = true;
        if (ev.stopPropagation) {
            ev.stopPropagation();
        }
        return true;
    }
    elem = this;
    var togglePattern = new RegExp('(^|\\s)toggle_(hide|show|show-apply)(\\s|$)');
    var p = elem.parentNode;
    while (!togglePattern.test(p.className)) {
        if (!p.parentNode) {
            break;
        }
        p = p.parentNode;
    }
    var hidePattern = new RegExp('(^|\\s)toggle_hide(\\s|$)');
    var isVisible = hidePattern.test(p.className);
    if (!isVisible) {
        replaceClassName(p, 'toggle_show-apply', 'toggle_hide');
        replaceClassName(p, 'toggle_show', 'toggle_hide');
    } else {
        replaceClassName(p, 'toggle_hide', 'toggle_show-apply');
    }
    return true;
};

var initToggles = function(node) {
    if (!node) {
        node = document;
    }
    var toggleFunc = toggle;
    var toggleList = jQuery(".toggle_hide, .toggle_show", node);
    toggleList.each(function() {
        var togglers = jQuery(".entry_visible, .entry_visible_orange", this);
        togglers.each(function() {
            jQuery(this).click(toggleFunc);
        });
        replaceClassName(this, "toggle_show", "toggle_show-apply");
    });
};

var toggleHeight = function(gallery, stateA, stateB) {
    var $gallery = jQuery(gallery);
    if ($gallery.css('height')==stateA) {
        $gallery.css('height', stateB);
        return false;
    } else {
        $gallery.css('height', stateA);
        return true;
    }
};

var setChecked = function(name, selected, node) {
    var cbs = jQuery("input[name^='"+name+"']:checkbox", node);
    cbs.attr("checked", selected ? "checked" : "");
};

var confirmPassword = function(pw, pwConf) {
    var response = "false";
    if (pw.length<6 || pwConf.length<6) {
        response = "Password too short! Please enter at least 6 characters...";
    } else {
        response = (pw==pwConf) ? "true" : "Password confirmation failed";
    }
    return response;
};

var addProgressIndicator = function(node) {
    var $node = jQuery(node);
    if (!(jQuery(".progressindicator", node).length)) {
        $node.children().css("opacity", 0.5);
        $node.prepend(jQuery('<div class="progressindicator"><img src="/images/progress_indicator.gif"/></div>'));
    }
};

var removeProgressIndicator = function(node) {
    var $node = jQuery(node);
    $node.children().css("opacity", 1);
    jQuery(".progressindicator", node).remove();
};

var loadForm = function(form, url, data, success) {
    var $form = jQuery(form).wrapAll("<div/>").parent();
    addProgressIndicator($form);
    jQuery.ajax({
        type: "POST",
        url: url,
        data: data,
        success: function(response) {
            $form.replaceWith(response);
            $form = jQuery(form);
            initOverLabels($form);
            initToggles($form);
            if (typeof(success)=="function") {
                success(response);
            }
        },
        error: function(response) {
            removeProgressIndicator($form);
            $form.replaceWith($form.html());
        }
    });
};

var sendForm = function(form, target, url, data, onfinish) {
    var $form = jQuery(form);
    addProgressIndicator($form);
    $form.ajaxSubmit({
        success: function(response) {
            loadForm(target, url, data, onfinish);

            removeProgressIndicator($form);
        }
    });
};

jQuery(function() {
    // Initialize nested form labels
    initOverLabels();
    // Initialize toggled elements
    initToggles();
    // Preload progress indicator image
    //jQuery("<img/>").attr("src", "/images/progress_indicator.gif");
});

var formatCoords = function(lon, lat, prec) {
    var toDeg = function(par) {
        if (par<0) { par*=-1; }
        var deg = par;
        var min = (par-parseInt(par))*60.0;
        var sec = (min-parseInt(min))*60.0;
        return [parseInt(deg), parseInt(min), parseInt(sec)];
    }

    if (lon && lat) {
        var lonParts = toDeg(parseFloat(lon));
        var degLon = lonParts[0];
        var minLon = lonParts[1];
        var secLon = lonParts[2];
        var dirLon = (lon<0) ? "W" : "E";

        var latParts = toDeg(parseFloat(lat));
        var degLat = latParts[0];
        var minLat = latParts[1];
        var secLat = latParts[2];
        var dirLat = (lat<0) ? "S" : "N";

        if (prec=="deg") {
            return [degLat + "° " + dirLat,
                   degLon + "° " + dirLon];
        } else if (prec=="min") {
            return [degLat + "° " + minLat + "' " + dirLat,
                   degLon + "° " + minLon + "' " + dirLon];
        } else {
            return [degLat + "° " + minLat + "' " + secLat + "'' " + dirLat,
                   degLon + "° " + minLon + "' " + secLon + "'' " + dirLon];
        }
    }
    return ["", ""];
};

var changeCoordsTag = function(geo, lon, lat, prec) {
  var coordsStr = formatCoords(lon, lat, prec);
  var lonStr = coordsStr[1];
  var latStr = coordsStr[0];

  jQuery("abbr.longitude", geo).attr("title", lon).text(lonStr);
  jQuery("abbr.latitude", geo).attr("title", lat).text(latStr);
};

var ascendToParent = function(node, parentClass) {
    var $parents = jQuery(node).parents();
    var parentsLen = $parents.length;
    var i;
    for (i=0; i<parentsLen; i++) {
        var $cur = jQuery($parents[i]);
        if ($cur.is(parentClass)) {
            return $cur;
        }
    }
    return jQuery(null);
};

var replaceImageVersion = function(imageNode, vOld, vNew) {
    var vOldStr = "/" + vOld + "/";
    var $image = jQuery(imageNode);
    if ($image.attr("src").search(vOldStr)>=0) {
        var vNewStr = "/" + vNew + "/";
        $image.attr("src", $image.attr("src").replace(vOldStr, vNewStr));
    }
    return true;
};

var showSearchResults = function(target) {
    loadForm(target, '/search.pt', {q:jQuery('#search *[name^=q]').val()});
};
