(function($){

    var phone_regex = /^(1-?)?(\([2-9]\d{2}\)|[2-9]\d{2})-?[2-9]\d{2}-?\d{4}$/;

    var states = ['AL','AK','AS','AZ','AR','CA','CO','CT','DE','DC','FM','FL','GA','GU','HI','ID','IL','IN','IA','KS','KY','LA','ME','MH','MD','MA','MI','MN','MS','MO','MT','NE','NV','NH','NJ','NM','NY','NC','ND','MP','OH','OK','OR','PW','PA','PR','RI','SC','SD','TN','TX','UT','VT','VI','VA','WA','WV','WI','WY'];
    
    
    
    if ($.validator) {
        $.validator.addMethod("notEqualTo", function(value, element, param) {
            return this.optional(element) || value !== param;
        }, "Please select a value");
        $.validator.addMethod("match", function(value, element, param) {
            return this.optional(element) || value.match(new RegExp("^(" + param + ")$", "i"));
        });
        $.validator.addMethod("endswith", function(value, element, param) {
            return this.optional(element) || (value.match(param+'$')==param);
        }, $.format('Please enter in a value that ends with {0}'));
        $.validator.addMethod('extension_alias', function(extension_alias, element) {
            return this.optional(element) || $.helpers.is_valid_extension(extension_alias);
        }, "System extensions 211, 311, 411, 511, 611, 711, 811, 911 and between 899 to 999 cannot be used");
        $.validator.addMethod("phoneUS", function(phone_number, element) {
            phone_number = phone_number.replace(/\s+/g, "");
            var valid = phone_number.length > 9 && phone_number.match(phone_regex);
            return this.optional(element) || valid;
        }, "Please specify a valid phone number");
        $.validator.addMethod('phone_number', function(phone_number, element) {
            phone_number = phone_number.replace(/\s+|_+/g, "");
            var valid = false;
            var stripped_phone_number = $.stripChars(phone_number);
            if (stripped_phone_number.length >= 6) {
                valid = stripped_phone_number.length > 9 && phone_number.match(phone_regex);
            } else if (stripped_phone_number.length >= 3) {
                valid = $.helpers.is_valid_extension(phone_number);
            }
            return this.optional(element) || valid;
        }, "Please specify a valid phone number or extension");
        $.validator.addMethod('extension_domestic_international_phone_number', function(phone_number, element) {
            phone_number = phone_number.replace(/\s+/g, "");
            var valid = false;
            var stripped_phone_number = $.stripChars(phone_number);
            if (stripped_phone_number.length >= 11) { // international
                valid = /^011\d+$/.test(phone_number);
            } else if (stripped_phone_number.length >= 6) { // domestic
                valid = stripped_phone_number.length > 9 && phone_number.match(phone_regex);
            } else if (stripped_phone_number.length >= 3) { // extension
                valid = /^\d+$/.test(phone_number);
            }
            return this.optional(element) || valid;
        }, "Please specify a valid extension, phone number, or international phone number without any additional characters");
        $.validator.addMethod('just_phone_number', function(phone_number, element) {
            phone_number = phone_number.replace(/\s+/g, "");
            var valid = phone_number.length > 9 && phone_number.match(phone_regex);
            return this.optional(element) || valid;
        }, "Please specify a valid phone number or extension");
        $.validator.addMethod('mac_address', function(mac, element) {
            return this.optional(element) || mac.match(/(^([0-9a-fA-F]{2}([:]|$)){6}$|^[0-9a-fA-F]{12}$)/);
        }, "Please specify a valid MAC address <em>(00:12:34:ab:cd:ef)</em>");
        $.validator.addMethod('notEqualToValueInObject', function(value, element, params) {
            return this.optional(element) || value != params[0][params[1]];
        }, "Passcodes cannot equal each other");
        $.validator.addMethod('just_username', function(value, element, params) {
            return this.optional(element) || /^[a-zA-Z0-9\_\.]+$/.test(value);
        }, "Username is not valid");
        $.validator.addMethod('just_domain', function(value, element, params) {
            return this.optional(element) || /^((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value);
        }, "Domain is not valid");

        $.validator.addMethod('unique_in_values', function(value, element, params) {
            var val = (params.prefix || '') + value + (params.suffix || '');
            var exists = false;
            $.each(params.values, function() {
                exists = (val == this.toString());
                return !exists;
            });
            return this.optional(element) || !exists;
        }, "Value already exists");
        // ensures a form with 4 text input elements which form an ip address is unique to the list of addresses passed in params.values
        // params must contain: 
        //     selector - the jquery selector which must return the 4 text input fields
        //     values - collection of the existing ip address strings
        $.validator.addMethod('unique_ip', function(value, element, params) {
            var values = [];
            // populate array with the values of the forms text input elements
            $(params.selector).each(function(){ values.push($(this).val()) });
            // create a string of the ip address
            var newip = values.join('.');
            // delegate to unique_in_values method to see if the newip is already in the list
            var existing_values = $(params.data_id).data(params.data_key);
            params.values = existing_values;
            return $.validator.methods.unique_in_values.call(this, newip, element, params);
        }, "This ip is already registered.");

        $.validator.addMethod('alpha', function(value, element, params) {
            return this.optional(element) || /^[a-zA-Z]+$/.test(value);
        }, "Contains non-alpha characters");
        $.validator.addMethod('alphanumeric', function(value, element, params) {
            return this.optional(element) || /^[a-zA-Z0-9]+$/.test(value);
        }, "Only letters and numbers can be used");
        $.validator.addMethod('state_abbr', function(value, element, params) {
            if (value) value=value.toUpperCase();
            return this.optional(element) || ($.inArray(value, states) != -1);
        }, "Must be a state abbreviation");
        $.validator.addMethod('does_not_start_with_zero', function(value, element, params) {
        	return this.optional(element) || !(/^0/.test(value));
        }, "Cannot start with zero");
        $.validator.addMethod('past', function (value, element, params) {
            var now = new Date();
            return this.optional(element) || now >= new Date(value);
        }, "Selected date must be in the past.");
        $.validator.addClassRules('extension',{
            required: true,
            digits: true,
            minlength: 3,
            maxlength: 5
        });
        $.validator.addClassRules('short_state',{
            alpha:true
        });
    }

    if ($.editable) {
        $.editable.addInputType('password', {
            element : function(settings, original) {
                var input = $('<input />');
                if (settings.width  != 'none') {
                    input.width(settings.width);
                }
                if (settings.height != 'none') {
                    input.height(settings.height);
                }
                /* https://bugzilla.mozilla.org/show_bug.cgi?id=236791 */
                //input[0].setAttribute('autocomplete','off');
                input.attr('autocomplete','off');
                input.attr('type','password');
                $(this).append(input);
                return(input);
            },
            content : function() {
                $(':input:first', this).val('');
            }
        });
        $.editable.addInputType('address', {
            element: function(settings, original) {
            $(this).setTemplateURL($.template('/address_input.jt')).processTemplate();
            return $('#address_json', this);
            },
            submit: function(settings, original) {
                var value = {
                        line1: $('#address_line1', this).val(),
                        line2: $('#address_line2', this).val(),
                        city: $('#address_city', this).val(),
                        state: $('#address_state', this).val(),
                        zip: $('#address_zip', this).val()
                };
                $('#address_json', this).val($.toJSON(value));
            },
            content: function(htmlString, settings, original) {
                var html = $('<div></div>');
                html.html(htmlString);
                $('#address_line1', this).val(html.find('.line1').text());
                $('#address_line2', this).val(html.find('.line2').text());
                $('#address_city', this).val(html.find('.city').text());
                $('#address_state', this).val(html.find('.state').text());
                $('#address_zip', this).val(html.find('.zip').text());
            }
        });
        $.editable.addInputType('select_music', {
            element : function(settings, original) {
                var $this = $(this);
                var select = $('<div><div class="music_select"><select /><a class="play_media" href="#" style="margin-left:10px;"><img src="/pb/assets/images/ivr/play.png" alt="Play this file." title="Play this file" style="height:16px;width:16px"/></a></div></div>');
                $this.append(select);
                return $this.find('select');
            },
            content : function(data, settings, original) {
                var form = this,
                    select = $('select', form);
                /* If it is string assume it is json. */
                if (String == data.constructor) {
                    eval ('var json = ' + data);
                } else {
                /* Otherwise assume it is a hash already. */
                    var json = data;
                }
                for (var key in json) {
                    if (!json.hasOwnProperty(key)) {
                        continue;
                    }
                    if ('selected' == key) { // 'selected' is a special value in the object
                        continue;
                    }
                    var option = $('<option />').val(key).append(json[key]);
                    select.append(option);
                }
                
                var audio_play_logic = function(val) {
                    // set the play button to play the current audio
                    var play_media = form.find('a.play_media');
                    play_media.unbind('click.play_media');
                    if (val === 'undefined') {
                        // because we can't currently play the default audio :(
                        play_media.hide();
                    } else {
                        // needs to be a click handler because need to dynamically source from select
                        play_media.show().bind('click.play_media', function() {
                            $(document).trigger('play_prompt', [{name:select.val()}])
                        });
                    }                    
                };
                
                /* Loop option again to set selected. IE needed this... */
                select.children().each(function() {
                    var $this = $(this);
                    if ($this.val() == json['selected'] || $this.text() == $.trim(original.revert)) {
                        $this.attr('selected', 'selected');
                        audio_play_logic($this.val());
                    }
                });
                select.change(function() {
                    audio_play_logic($(this).val());
                });
            }
        });
    }

})(jQuery);

