/**
 * jquery.numberformatter - Formatting/Parsing Numbers in jQuery
 * Written by Michael Abernethy (mike@abernethysoft.com)
 *
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * Date: 1/26/08
 *
 * @author Michael Abernethy
 * @version 1.1.0
 *
 *
 * This plugin can be used to format numbers as text and parse text as Numbers
 * Because we live in an international world, we cannot assume that everyone
 * uses "," to divide thousands, and "." as a decimal point.
 *
 * The format() function will take the text within any selector by calling
 * text() or val() on them, getting the String, and applying the specified format to it.
 * It will return the jQuery object
 *
 * The parse() function will take the text within any selector by calling text()
 * or val() on them, turning the String into a Number, and returning these
 * values in a Number array.
 * It WILL BREAK the jQuery chain, and return an Array of Numbers.
 *
 * The syntax for the formatting is:
 * 0 = Digit
 * # = Digit, zero shows as absent
 * . = Decimal separator
 * - = Negative sign
 * , = Grouping Separator
 * % = Percent (multiplies the number by 100)
 * For example, a format of "#,###.00" and text of 4500.20 will
 * display as "4.500,20" with a locale of "de", and "4,500.20" with a locale of "us"
 *
 *
 * As of now, the only acceptable locales are 
 * United States -> "us"
 * Arab Emirates -> "ae"
 * Egypt -> "eg"
 * Israel -> "il"
 * Japan -> "jp"
 * South Korea -> "kr"
 * Thailand -> "th"
 * China -> "cn"
 * Hong Kong -> "hk"
 * Taiwan -> "tw"
 * Australia -> "au"
 * Canada -> "ca"
 * Great Britain -> "gb"
 * India -> "in"
 * Germany -> "de"
 * Vietnam -> "vn"
 * Spain -> "es"
 * Denmark -> "dk"
 * Austria -> "at"
 * Greece -> "gr"
 * Brazil -> "br"
 * Czech -> "cz"
 * France  -> "fr"
 * Finland -> "fi"
 * Russia -> "ru"
 * Sweden -> "se"
 * Switzerland -> "ch"
 * 
 * TODO
 * Separate positive and negative patterns separated by a ":" (e.g. use (#,###) for accounting)
 * More options may come in the future (currency)
 **/
     
 (function(jQuery) {

     function FormatData(dec, group, neg) {
         this.dec = dec;
         this.group = group;
         this.neg = neg;
     };

     function formatCodes(locale) {

         // default values
         var dec = ".";
         var group = ",";
         var neg = "-";

         if (locale == "us" ||
             locale == "ae" ||
             locale == "eg" ||
             locale == "il" ||
             locale == "jp" ||
             locale == "sk" ||
             locale == "th" ||
             locale == "cn" ||
             locale == "hk" ||
             locale == "tw" ||
             locale == "au" ||
             locale == "ca" ||
             locale == "gb" ||
             locale == "in"
            ) {
             dec = ".";
             group = ",";
         }

         else if (locale == "de" ||
             locale == "vn" ||
             locale == "es" ||
             locale == "dk" ||
             locale == "at" ||
             locale == "gr" ||
             locale == "br"
            ) {
             dec = ",";
             group = ".";
         }
         else if (locale == "cz" ||
              locale == "fr" ||
             locale == "fi" ||
             locale == "ru" ||
             locale == "se"
            ) {
             group = " ";
             dec = ",";
         }
         else if (locale == "ch") {
             group = "'";
             dec = ".";
         }

         return new FormatData(dec, group, neg);

     };

     jQuery.formatNumber = function(number, options) {
         var options = jQuery.extend({}, jQuery.fn.parse.defaults, options);
         var formatData = formatCodes(options.locale.toLowerCase());

         var dec = formatData.dec;
         var group = formatData.group;
         var neg = formatData.neg;

         var numString = new String(number);
         numString = numString.replace(".", dec).replace("-", neg);
         return numString;
     };

     jQuery.fn.parse = function(options) {

         var options = jQuery.extend({}, jQuery.fn.parse.defaults, options);

         var formatData = formatCodes(options.locale.toLowerCase());

         var dec = formatData.dec;
         var group = formatData.group;
         var neg = formatData.neg;

         var valid = "1234567890.-";

         var array = [];
         this.each(function() {

             var text = new String(jQuery(this).text());
             if (jQuery(this).is(":input"))
                 text = new String(jQuery(this).val());

             // now we need to convert it into a number
             text = text.replace(group, '').replace(dec, ".").replace(neg, "-");
             var validText = "";
             var hasPercent = false;
             if (text.charAt(text.length - 1) == "%")
                 hasPercent = true;
             for (var i = 0; i < text.length; i++) {
                 if (valid.indexOf(text.charAt(i)) > -1)
                     validText = validText + text.charAt(i);
             }
             var number = new Number(validText);
             if (hasPercent) {
                 number = number / 100;
                 number = number.toFixed(validText.length - 1);
             }
             array.push(number);
         });

         return array;
     };

     jQuery.fn.format2 = function(options) {

         var options = jQuery.extend({}, jQuery.fn.format.defaults, options);

         var formatData = formatCodes(options.locale.toLowerCase());

         var dec = formatData.dec;
         var group = formatData.group;
         var neg = formatData.neg;

         var validFormat = "0#-,.";

         return this.each(function() {
             var text = new String(jQuery(this).text());
             if (jQuery(this).is(":input"))
                 text = new String(jQuery(this).val());

             // strip all the invalid characters at the beginning and the end
             // of the format, and we'll stick them back on at the end
             // make a special case for the negative sign "-" though, so 
             // we can have formats like -$23.32
             var prefix = "";
             var negativeInFront = false;
             for (var i = 0; i < options.format.length; i++) {
                 if (validFormat.indexOf(options.format.charAt(i)) == -1)
                     prefix = prefix + options.format.charAt(i);
                 else if (i == 0 && options.format.charAt(i) == '-') {
                     negativeInFront = true;
                     continue;
                 }
                 else
                     break;
             }
             var suffix = "";
             for (var i = options.format.length - 1; i >= 0; i--) {
                 if (validFormat.indexOf(options.format.charAt(i)) == -1)
                     suffix = options.format.charAt(i) + suffix;
                 else
                     break;
             }

             options.format = options.format.substring(prefix.length);
             options.format = options.format.substring(0, options.format.length - suffix.length);


             // now we need to convert it into a number
             var number = new Number(text.replace(group, '').replace(dec, ".").replace(neg, "-"));

             // special case for percentages
             if (suffix == "%")
                 number = number * 100;

             var returnString = "";

             var decimalValue = number % 1;
             if (options.format.indexOf(".") > -1) {
                 var decimalPortion = dec;
                 var decimalFormat = options.format.substring(options.format.lastIndexOf(".") + 1);
                 var decimalString = new String(decimalValue.toFixed(decimalFormat.length));
                 decimalString = decimalString.substring(decimalString.lastIndexOf(".") + 1);
                 for (var i = 0; i < decimalFormat.length; i++) {
                     if (decimalFormat.charAt(i) == '#' && decimalString.charAt(i) != '0') {
                         decimalPortion += decimalString.charAt(i);
                         break;
                     }
                     else if (decimalFormat.charAt(i) == "0") {
                         decimalPortion += decimalString.charAt(i);
                     }
                 }
                 returnString += decimalPortion
             }
             else
                 number = Math.round(number);

             var ones = Math.floor(number);
             if (number < 0)
                 ones = Math.ceil(number);

             var onePortion = "";
             if (ones == 0) {
                 onePortion = "0";
             }
             else {
                 // find how many digits are in the group
                 var onesFormat = "";
                 if (options.format.indexOf(".") == -1)
                     onesFormat = options.format;
                 else
                     onesFormat = options.format.substring(0, options.format.indexOf("."));
                 var oneText = new String(ones);
                 var groupLength = 9999;
                 if (onesFormat.lastIndexOf(",") != -1)
                     groupLength = onesFormat.length - onesFormat.lastIndexOf(",") - 1;
                 var groupCount = 0;
                 for (var i = oneText.length - 1; i > -1; i--) {
                     onePortion = oneText.charAt(i) + onePortion;

                     groupCount++;

                     if (groupCount == groupLength && i != 0) {
                         onePortion = group + onePortion;
                         groupCount = 0;
                     }

                 }
             }

             returnString = onePortion + returnString;

             // handle special case where negative is in front of the invalid
             // characters
             if (number < 0 && negativeInFront && prefix.length > 0) {
                 returnString = returnString.substring(1);
                 prefix = neg + prefix;
             }

             returnString = prefix + returnString + suffix;

             if (returnString.indexOf("-,") > -1)
                 returnString = returnString.replace(/-,/g, "-");
                 
             if (jQuery(this).is(":input"))
                 jQuery(this).val(returnString);
             else
                 jQuery(this).text(returnString);

         });
     };

     jQuery.fn.parse.defaults = {
         locale: "us"
     };

     jQuery.fn.format.defaults = {
         format: "#,###.00",
         locale: "us"
     };


 })(jQuery);
