﻿var PEW = window.PEW || {};
PEW.ShareThis = (function () {

    //# Private Constants
    var EMAIL_ACTIVE_CLASS = "mail-active";
    var EMAIL_SERVICE_URL = "/EmailShare.asmx/Send";
    var ELEMENT_SELECTORS = {
        emailOverlayTrigger: "a.mail",
        emailOverlay: ".mail-overlay",
        emailOverlayMessageContainer: ".mail-overlay .message-container",
        emailSubmit: ".mail-overlay input[type=image]",
        emailInput: ".mail-overlay input[type=text]",
        emailFormFields: ".mail-overlay input[type=text], .mail-overlay textarea",
        emailOverlayCloseTrigger: ".mail-overlay .close",
        printTrigger: "a.print",
        shareOverlayTrigger: "a.sharethis",
        shareOverlay: ".sharethis-overlay",
        shareOverlayExpandTrigger: ".sharethis-overlay .expand",
        shareCollapsedListItems: ".sharethis-overlay .social-networks li.expanded"
    };
    var PUBLISHER_ID = "65d53d3e-c31a-43bd-b8e8-c08b002adc88";
    //#

    //# Private Attributes
    var _isEmailOverlayVisible = false;
    var _activeOverlay;
    var _activeOverlayTrigger;
    //#

    //# Private Methods
    /**
    * @param trigger Expected to implement jQuery Element Interface
    * @param overlay Expected to implement jQuery Element Interface
    */
    var _showOverlay = function (trigger, overlay) {

        if (!overlay) throw new Error("Overlay was null or not defined");
        if (!trigger) throw new Error("Overlay Trigger was null or not defined");

        if (_activeOverlay) {
            _activeOverlayTrigger.trigger("click");
        }

        overlay.css({
            top: trigger.position().top + trigger.height(),
            left: trigger.position().left - overlay.outerWidth() + trigger.width()
        }).fadeIn("fast", function () {
            _activeOverlay = jQuery(overlay);
            _activeOverlayTrigger = jQuery(trigger);
        });
    };
    /**
    * @param overlay Expected to implement jQuery Element Interface
    */
    var _hideOverlay = function (overlay, eventCompleteHandler) {
        if (!overlay) throw new Error("Overlay was null or not defined.");
        overlay.fadeOut("fast", function () {
            _activeOverlayTrigger = null;
            _activeOverlay = null;
            if (eventCompleteHandler && typeof eventCompleteHandler === "function") {
                eventCompleteHandler.call(this);
            }
        });
    };
    var _expandShareOverlay = function (event) {
        jQuery(ELEMENT_SELECTORS.shareOverlayExpandTrigger).hide();
        jQuery(ELEMENT_SELECTORS.shareCollapsedListItems).fadeIn("fast");
        return false;
    };

    /**
    * Toggle the element's color attribute based on the element's value.
    * If the element is null, nothing will happen.
    * If the element does not have a defaultValue attribte, or the defaultAttribute is an empty string, then the activeColor will be used.
    * If the element's value is an empty string or not the defaultValue then the color 'active' will be used.
    * If the element's value is the element's defaultValue (specified by the element's html attribute 'defaultValue') then the color 'inactive' will be used.
    *
    * @param element - This is the element to modify.
    * @param activeColor - Hex value for the Active color (include '#', eg. #222) this is optional, the default value is #333.
    * @param inactiveColor - Hex value for the Inactive color (include '#', eg. #DDD) this is optional, the default value is #CCC.
    */
    var _toggleInputColor = function (element, activeColor, inactiveColor) {
        activeColor = activeColor || "#333";
        inactiveColor = inactiveColor || "#CCC";

        if (!element) return;

        if (element.val() == element.attr("defaultValue") && element.val() != "") {
            element.css("color", inactiveColor);
        } else {
            element.css("color", activeColor);
        }
    };

    /**
    * Checks the given element and sets it's value to the 'defaultValue', taken from the element's html attribute 'defaultValue'.
    * If the element is null, or if the element does not have an attribute named 'defaultValue', then nothing will happen.
    * Otherwise, if the element's value is set to an empty string, the value will be set to the default value.
    * Or, if the current value is equal to the default value, the value will be set to an empty string.
    * 
    * @param element - The element to check.
    */
    var _toggleInputValue = function (element) {

        if (!element) return;
        if (!element.attr("defaultValue")) return;

        if (element.val() === "") {
            element.val(element.attr("defaultValue"));
        } else if (element.val() === element.attr("defaultValue")) {
            element.val("");
        }

    };

    /**
    * Returns true if the input string is a valid email address, false otherwise 
    *
    * @param inputString - the input string to test
    */
    var _isValidEmailAddress = function (inputString) {
        if (!inputString) return false;
        if (typeof inputString !== "string") return false;

        return /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/.test(inputString);
    };

    var _sendEmail = function (pageUrl, pageTitle, fromName, fromEmail, toName, toEmail, subject, message, callback) {
        var serviceData = "{ \"pageUrl\": \"" + pageUrl + "\" , \"pageTitle\" : \"" + pageTitle + "\", \"fromName\" : \"" + fromName
            + "\", \"fromEmail\" : \"" + fromEmail + "\", \"toName\" : \"" + toName + "\", \"toEmail\" : \"" + toEmail + "\", \"subject\" : \"" + subject + "\", \"message\" : \"" + message + "\" }";

        jQuery.ajax({
            url: EMAIL_SERVICE_URL,
            type: "POST",
            contentType: "application/json",
            success: function (data) {
                if (data.d && callback && callback.successHandler && typeof callback.successHandler === "function") {
                    callback.successHandler();
                } else if (callback && callback.failureHandler && typeof callback.failureHandler === "function") {
                    callback.failureHandler();
                } else {
                    throw new Error("AJAX Request failure and no handler was provided.");
                }
            },
            failure: function (data) {
                if (callback && callback.failureHandler && typeof callback.failureHandler === "function") {
                    callback.failureHandler();
                }
            },
            processData: false,
            data: serviceData
        });
    };
    var _displayMessage = function (container, message, cssClasses) {

        _clearMessage(container);

        container.append("<p class=\"message\">" + message + "</p>");

        if (cssClasses) {
            jQuery(cssClasses).each(function (index, item) {
                jQuery("p.message", container).addClass(item);
            });
        }
    };
    var _displayErrorMessage = function (message) {
        var container = jQuery(ELEMENT_SELECTORS.emailOverlay);
        container.append("<p class=\"message error\">" + message + "</p>");
    };
    var _clearMessage = function (container) {
        if (jQuery("p.message", container)) {
            jQuery("p.message", container).remove();
        }
    };


    /**
    * Handle Submission of the Email Form
    * 
    *
    */
    var _submitEmailForm = function () {

        // iterate over each '.required' and '.type-email' elements, and check to make sure each is valid
        var isFormValid = true;

        jQuery(".mail-overlay .required").each(function () {

            var field = jQuery(this);
            var defaultValue = field.attr("defaultValue") || undefined;
            var label = _findFieldLabel(field);

            if (field.val() == "" || (defaultValue !== undefined && field.val() === defaultValue)) {
                _markFieldInvalid(field, jQuery(ELEMENT_SELECTORS.emailOverlayMessageContainer), (label || this.id) + " is a required field.");
            } else {
                _markFieldValid(field, jQuery(ELEMENT_SELECTORS.emailOverlayMessageContainer));
            }

        });
        jQuery(".mail-overlay .type-email").each(function () {

            var field = jQuery(this);
            var label = _findFieldLabel(field);
            if (!_isValidEmailAddress(field.val())) {
                _markFieldInvalid(field, jQuery(ELEMENT_SELECTORS.emailOverlayMessageContainer), (label || this.id) + " is a not a valid email address.");
            } else {
                _markFieldValid(field, jQuery(ELEMENT_SELECTORS.emailOverlayMessageContainer));
            }
        });


        jQuery(".mail-overlay .required, .mail-overlay .type-mail").each(function (index, element) {
            isFormValid = isFormValid && jQuery(element).data("valid");
        });

        if (isFormValid) {

            _hideEmailForm();

            jQuery(ELEMENT_SELECTORS.emailOverlay).css("width", jQuery(ELEMENT_SELECTORS.emailOverlay).width());
            jQuery(ELEMENT_SELECTORS.emailInput + "," + ELEMENT_SELECTORS.emailSubmit).hide();
            _displayMessage(jQuery(ELEMENT_SELECTORS.emailOverlay), "Sending Email");

            _sendEmail(window.location, jQuery("title").eq(0).html().trim().replace("&amp;", "&"), jQuery('#emailFromName').val(), jQuery('#emailFromAddress').val(), jQuery('#emailToName').val(), jQuery('#emailToAddress').val(),
                jQuery('#emailSubject').val(), jQuery('#emailMessage').val(), {
                    successHandler: function (event) {
                        _displayMessage(jQuery(ELEMENT_SELECTORS.emailOverlay), "Email has been sent.");
                    },
                    failureHandler: function (event) {
                        _displayMessage(jQuery(ELEMENT_SELECTORS.emailOverlay), "There was an error sending the email.", ["error"]);
                    }
                });
        }
    };

    var _hideEmailForm = function () {
        jQuery(".mail-overlay .required-fields, .mail-overlay .sender-row, .mail-overlay .recipient-row, .mail-overlay .subject-row, .mail-overlay .message-row, .mail-overlay .controls").hide();
    };

    var _showEmailForm = function () {
        jQuery(".mail-overlay .required-fields, .mail-overlay .sender-row, .mail-overlay .recipient-row, .mail-overlay .subject-row, .mail-overlay .message-row, .mail-overlay .controls").show();
    };

    /**
    * Hide the Email overlay and cleanup any references
    */
    var _hideEmailOverlay = function (triggerElement) {
        _hideOverlay(jQuery(ELEMENT_SELECTORS.emailOverlay), function (event) {
            jQuery("form").unbind("submit");
            jQuery(window).unbind("keydown");
            jQuery(ELEMENT_SELECTORS.emailInput + "," + ELEMENT_SELECTORS.emailSubmit).show();
            _clearMessage(jQuery(ELEMENT_SELECTORS.emailOverlay));
            jQuery(ELEMENT_SELECTORS.emailInput).val(jQuery(ELEMENT_SELECTORS.emailInput).attr("defaultValue"));

            _showEmailForm();

            //Keep default values when the close button is clicked on
            _setDefaultFormValues();
        });
        triggerElement.removeClass(EMAIL_ACTIVE_CLASS);
        _isEmailOverlayVisible = false;
    };

    var _setDefaultFormValues = function () {
        jQuery("#emailFromName").val(jQuery("#emailFromName").attr("defaultValue") || "Your Name");
        jQuery("#emailFromAddress").val(jQuery("#emailFromAddress").attr("defaultValue") || "Your Email");
        jQuery("#emailToName").val(jQuery("#emailToName").attr("defaultValue") || "Recipient's Name");
        jQuery("#emailToAddress").val(jQuery("#emailToAddress").attr("defaultValue") || "Recipient's Email");

        var title = jQuery("title").eq(0).html().trim().replace("&amp;","&");

        jQuery("#emailSubject").val("PewCenterontheStates.org: " + title);
        jQuery("#emailMessage").val("I wanted to share this Pew Center on the States page with you: " + window.location.href);
    };

    /**
    * Show the Email overlay and setup any references
    */
    var _showEmailOverlay = function (triggerElement) {
        _showOverlay(triggerElement, jQuery(ELEMENT_SELECTORS.emailOverlay));
        triggerElement.addClass(EMAIL_ACTIVE_CLASS);
        _isEmailOverlayVisible = true;
    };

    /**
    * Marks an input field or textarea as invalid
    *
    * @param element - the input field or textarea to mark invalid.
    */
    var _markFieldInvalid = function (element, container, message) {
        if (!element) return;

        element.data("valid", false);
        element.addClass("error");

        if (container && message && (jQuery("." + element.attr("id") + "_message", container).length == 0)) {
            jQuery(container).append("<p class=\"" + element.attr("id") + "_message error message\">" + message + "</p>");
        }
    };
    /**
    * Marks an input field or textarea as valid
    *
    * @param element - the input field or textarea to mark valid.
    */
    var _markFieldValid = function (element, container) {
        if (!element) return;

        element.data("valid", true);
        element.removeClass("error");

        if (container) {
            jQuery("." + element.attr("id") + "_message", container).remove();
        }
    };

    /**
    * Get Field label
    * Trys to find the associated label element which has the attribute for=[input_id] and grabs the contents of that label.
    * This method will strip ":" from the value.
    *
    * @param element - The element to find the matching label.
    * @return The element's label, or undefined if no matching label is found.
    */
    var _findFieldLabel = function (element) {
        if (!element) return undefined;

        var label = jQuery("label[for=\"" + element.attr("id") + "\"]");

        if (!label) return undefined;

        return label.text().replace(":", "");
    };
    //#

    //# Constructor
    stLight.options({ publisher: PUBLISHER_ID });
    //#

    //Shortcut to grab element from DOM
    var $ = function (id) {
        return document.getElementById(id);
    }

    //Set a trim method to remove the white space before text in the mail-overlay
    String.prototype.trim = function () {
        return this.replace(/^\s+/, "");
    }


    //# Public Interface
    return {
        init: function () {
            
            _setDefaultFormValues();

            // Wireup Email Overlay Trigger
            jQuery(ELEMENT_SELECTORS.emailOverlayTrigger).click(function (event) {
                if (_isEmailOverlayVisible) {
                    _hideEmailOverlay(jQuery(this));
                } else {
                    _showEmailOverlay(jQuery(this));
                }
                return false;
            });

            // Wireup Email Overlay Close Trigger 
            jQuery(ELEMENT_SELECTORS.emailOverlayCloseTrigger).click(function () {
                _hideEmailOverlay(jQuery(ELEMENT_SELECTORS.emailOverlayTrigger));
                return false;
            });

            // Wireup Form Submit Button
            jQuery(ELEMENT_SELECTORS.emailSubmit).click(function (event) {
                _submitEmailForm(event);
                return false;
            });


            // Wireup Handlers for Form Field Focus In/Out Functionality
            jQuery(ELEMENT_SELECTORS.emailFormFields).focusin(function (event) {
                _toggleInputValue(jQuery(this));
                _toggleInputColor(jQuery(this));

                jQuery("form").submit(function () { return false; });
                jQuery(window).keydown(function (keyEvent) {
                    if (keyEvent.keyCode == 13 /* Enter Key */) {
                        _submitEmailForm();
                    }
                });

            }).focusout(function (event) {
                _toggleInputValue(jQuery(this));
                _toggleInputColor(jQuery(this));

                jQuery("form").unbind("submit");
                jQuery(window).unbind("keydown");
            });

            // Set all required/type-email fields to have a default invalid state
            jQuery(".mail-overlay .required, .mail-overlay .type-email").data("valid", false);

            // Wireup Form Validation Handlers
            jQuery(".mail-overlay .required").focusout(function () {

                var field = jQuery(this);
                var defaultValue = field.attr("defaultValue") || undefined;
                var label = _findFieldLabel(field);

                if (field.val() == "" || (defaultValue !== undefined && field.val() === defaultValue)) {
                    _markFieldInvalid(field, jQuery(ELEMENT_SELECTORS.emailOverlayMessageContainer), (label || this.id) + " is a required field.");
                } else {
                    _markFieldValid(field, jQuery(ELEMENT_SELECTORS.emailOverlayMessageContainer));
                }

            });
            jQuery(".mail-overlay .type-email").focusout(function () {

                var field = jQuery(this);
                var label = _findFieldLabel(field);
                if (!_isValidEmailAddress(field.val())) {
                    _markFieldInvalid(field, jQuery(ELEMENT_SELECTORS.emailOverlayMessageContainer), (label || this.id) + " is a not a valid email address.");
                } else {
                    _markFieldValid(field, jQuery(ELEMENT_SELECTORS.emailOverlayMessageContainer));
                }
            });

            // Wireup Event Handler for Print Button
            jQuery(ELEMENT_SELECTORS.printTrigger).click(function () { window.print(); return false; });

            // Wireup Event Handlers for Share Overlay
            jQuery(ELEMENT_SELECTORS.shareOverlayTrigger).toggle(function (event) {
                _showOverlay(jQuery(ELEMENT_SELECTORS.shareOverlayTrigger), jQuery(ELEMENT_SELECTORS.shareOverlay));
                jQuery(ELEMENT_SELECTORS.shareOverlayTrigger).addClass("active");
                return false;
            }, function (event) {
                _hideOverlay(jQuery(ELEMENT_SELECTORS.shareOverlay), function () {
                    jQuery(ELEMENT_SELECTORS.shareCollapsedListItems).hide();
                    jQuery(ELEMENT_SELECTORS.shareOverlayExpandTrigger).show();
                    jQuery(ELEMENT_SELECTORS.shareOverlayTrigger).removeClass("active");
                });
                return false;
            });
            jQuery(ELEMENT_SELECTORS.shareOverlayExpandTrigger).click(_expandShareOverlay);
        }
    };
    //#
})();


jQuery(document).ready(PEW.ShareThis.init);
