/******************************************************************************/

/******************************************************************************/


/******************************************************************************/
function validate_positive_number(str){
   if(!validate_nonempty(str)[0]){ return [true, "ignore empty str"]; }
   
   var value = parseInt(str, 10);
   
   if(isNaN(value)){
      return [false, "not a valid number"];
   }
   
   if(!isFinite(value)){
      return [false, "not a finite"];
   }
   
   if(value < 0){
      return [false, "negative number"];
   }
   
   return [true, "OK"];
}

/******************************************************************************/
function validate_price(str){
   if(!validate_nonempty(str)[0]){ return [true, "ignore empty str"]; }
   
   var priceRangeMax = MAX_MENU_PRICE;
   
   var price = null;
   
   var dotindex = str.indexOf(".");
   if(dotindex != -1){
      if(str.indexOf(".", dotindex + 1) != -1){
         return [false, "more than one decimal point"];
      }
            
      price = parseFloat(str);
      var change = str.substr(dotindex + 1, str.length);
      if(change.length > 2){
         return [false, "two digits after decimal point only"];
      }
   }else{
      price = parseInt(str, 10);
      
   }
   
   if(isNaN(price)){
      return [false, "not a valid number"];
   }
   
   if(!isFinite(price)){
         return [false, "not a finite"];
   }

   
   if(price <= 0){
      return [false, "value can not zero or less"];
   }
   
   if(price > priceRangeMax){
      return [false, "value to large (max: " + priceRangeMax.toFixed(2) + ")"];
   }
   
   return [true, "OK"];
}

/******************************************************************************/
function validate_date(str){
   if(!validate_nonempty(str)[0]){ return [true, "ignore empty str"]; }
   
   var date_formate = "mdy";
   var valid_seperators = ["/", "\\", "-", "."];
   var startYrange = 2000;
   var endYrange = 2100;
   
   var split_str = null;
   
   var firstindex = -1;
   for(i = 0; i < valid_seperators.length; i++){
      if((firstindex = str.indexOf(valid_seperators[i])) != -1){
         
         if(str.indexOf(valid_seperators[i], firstindex + 1) != -1){
            split_str = str.split(valid_seperators[i]);
         }else{
            // coudn't find second index
            return [false, "must include two seperator (try: \"" + valid_seperators[i] + "\")"];
         }
         break;
      }
   }   
   
   if(!split_str){
      return [false, "no valid date seperator (" + valid_seperators + ")"];
   }
   
   if(split_str.length != 3){
      return [false, "invalide number of paramiters"];
   }
   
   switch(date_formate){
   case "mdy":
      var month_str = split_str[0];
      var day_str = split_str[1];
      var year_str = split_str[2];
      break;
   case "ymd":
      var year_str = split_str[0];
      var month_str = split_str[1];
      var day_str = split_str[2];
      break;
   case "dmy":
      var day_str = split_str[0];
      var month_str = split_str[1];
      var year_str = split_str[2];
      break;
   }
   if(!validate_nonempty(month_str)){ return [false, "empty month field"]; }
   if(!validate_nonempty(day_str)){ return [false, "empty day field"]; }
   if(!validate_nonempty(year_str)){ return [false, "empty year field"]; }
   
   var month = parseInt(month_str, 10);
   var day = parseInt(day_str, 10);
   var year = parseInt(year_str, 10);
   
   if(isNaN(month)){ return [false, "month isn't a numeric"]; }
   if(isNaN(day)){ return [false, "day isn't a numeric"]; }
   if(isNaN(year)){ return [false, "year isn't a numeric"]; }
   
   if((month < 1) || (month > 12)){ return [false, "month not in valid range (" + "1-12" + ")"]; }
   if((day < 1) || (day > 31)){ return [false, "day not in valid range (" + "1-31" + ")"]; }
   if((year < startYrange) || (year > endYrange)){ return [false, "year not in valid range (" + startYrange + "-" + endYrange + ")"]; }
   
   
   return [true, "OK"];
}


/******************************************************************************/
function validate_nonempty(str){
   if(typeof str !== "string"){ return [false, "not a string?"]; }
   
   var emptyString = /^\s*$/;
   if(emptyString.test(str)){
      return [false, "(empty)"];
   }
   return [true, "OK"];
}

/******************************************************************************/
function validate_phone_number(str, type){
   if(!validate_nonempty(str)[0]){ return [true, "ignore empty str"]; }
   
   return [true, "OK"];
}

/******************************************************************************/
function validate_plaintext(str){
   if(!validate_nonempty(str)[0]){ return [true, "ignore empty str"]; }
   
 // make sure we don't have any invalide charicters
   var invalids = "\/\\\";:?!()\{\}^|";
   for(i = 0; i < invalids.length; i++){
      if(str.indexOf(invalids.charAt(i)) != -1){
         return [false, "invalide charicter"];
      }
   }
   
   // search for non-ascii
   for(i = 0; i < str.lenth; i++){
      if(str.charCodeAt(i) > 127){
         return [false, "non-ascii charicter"];
      }
   }
   
   return [true, "OK"]
}

/******************************************************************************/
function validate_url(str){
   if(!validate_nonempty(str)[0]){ return [true, "ignore empty str"]; }
   
   str = str.trim();
   
   //
   // lets think about how we realy want to do this 
   return [true, "OK"];
   //
   //
   
   /*var result = url.match("^(ftp|http|https):\/\/[A-Za-z0-9-]+\.[A-Za-z]{3}");
	if(result == null){
      // didn't match generic pattern
      return [false, "malformed url"];
   }*/
   
  /* var urlreg = /^(([\w]+:)?\/\/)?(([\d\w]|%[a-fA-f\d]{2,2})+(:([\d\w]|%[a-fA-f\d]{2,2})+)?@)?([\d\w][-\d\w]{0,253}[\d\w]\.)+[\w]{2,4}(:[\d]+)?(\/([-+_~.\d\w]|%[a-fA-f\d]{2,2})*)*(\?(&?([-+_~.\d\w]|%[a-fA-f\d]{2,2})=?)*)?(#([-+_~.\d\w]|%[a-fA-f\d]{2,2})*)?$/; 
   if(!urlreg.test(url)){
      return [false, "malformed url"];
   }*/
   
   /*
   var ldot = url.lastIndexOf(".");
   if(ldot != -1){
      if(!validate_tld(url.substring(ldot + 1, url.length))){
         return [false, "invalide tld"];
      }
   }
   */
	return [true, "OK"];
}

/******************************************************************************/
function validate_email_address(str){
   if(!validate_nonempty(str)[0]){ return [true, "ignore empty str"]; }
   
   var result = new Array(2);
   
   // remove any silly spaces around us
   str = str.trim();
   
   var lat = str.indexOf("@");
   var lstr = str.length;
   
   // cant have any paces
   if(str.indexOf(" ") != -1){
      return [false, "contains spaces"];
   }
   
   // make sure we don't have any invalide charicters
   var invalids = "\/\'\\ \";:?!()\{\}^|"; // [ ] are valide for IP emails
   for(i = 0; i < invalids.length; i++){
      if(str.indexOf(invalids.charAt(i)) != -1){
         return [false, "invalide charicter"];
      }
   }
   
   // search for non-ascii
   for(i = 0; i < str.lenth; i++){
      if(str.charCodeAt(i) > 127){
         return [false, "non-ascii charicter"];
      }
   }
   
   // cant have double dots
   if(str.indexOf("..") != -1){
      return [false, "double dots"];
   }
   
   if(str.indexOf(".@") != -1){
      return [false, "dot can't be next to @"];
   }
   if(str.indexOf("@.") != -1){
      return [false, "dot can't be next to @"];
   }
   
   // make sure we have a @ some place, not first or last
   if((lat == -1) || (lat == 0) || (lat == (lstr - 1))){
      return [false, "missing or incorrect @ location"];
   }
   
   // make sure no @ after the @
   if(str.indexOf("@", (lat + 1)) != -1){
      return [false, "multiple @ not allowed"];
   }
   
   // we cant begin with a dot
   if(str.charAt(0) == "."){
      return [false, "can't begin email with a dot"];
   }
   
   var username = str.substring(0, lat);
   var domain = str.substring(lat + 1, lstr);
   
   // check that the dot in domain isn't first or last and exists
   var ldot = domain.indexOf(".");
   if((ldot == -1) || (ldot == 0) || (ldot == (domain.length - 1))){
      return [false, "missing or incorrect dot in domain"];
   }
   
   // break of TLD and validate agains IANA
   var tld = domain.substring(domain.lastIndexOf(".") + 1, domain.length);
   var validtld = validate_tld(tld);
   if(!validtld[0]){
      if(tld.length == 2){
         // this could be a country code that we just don't know about
         // and our tld checker didn't catch, let it slide
         return [false, "invalide 2 letter TLD: " + tld];
      }else{
         return [false, "invalide TLD: " + tld];
      }
   }
   
   
   return [true, "OK"];
}

/******************************************************************************/
function validate_tld(tld){
   if(!validate_nonempty(tld)[0]){ return [true, "ignore empty str"]; }
   
   tld = tld.toUpperCase(tld);
   
   // http://data.iana.org/TLD/tlds-alpha-by-domain.txt
   var validTLDs = ["AERO","ARPA","ASIA","BIZ","CAT","COM","COOP","EDU","GOV",
                    "INFO","INT","JOBS","MIL","MOBI","MUSEUM","NAME","NET",
                    "ORG","PRO","TEL","TRAVEL"
                   ];

   var validCountryTLDs = ["AC","AD","AE","AF","AG","AI","AL","AM","AN","AO",
                           "AQ","AR","AS","AT","AU","AW","AX","AZ","BA","BB",
                           "BD","BE","BF","BG","BH","BI","BJ","BM","BN","BO",
                           "BR","BS","BT","BV","BW","BY","BZ","CA","CC","CD",
                           "CF","CG","CH","CI","CK","CL","CM","CN","CO","CR",
                           "CU","CV","CX","CY","CZ","DE","DJ","DK","DM","DO",
                           "DZ","EC","EE","EG","ER","ES","ET","EU","FI","FJ",
                           "FK","FM","FO","FR","GA","GB","GD","GE","GF","GG",
                           "GH","GI","GL","GM","GN","GP","GQ","GR","GS","GT",
                           "GU","GW","GY","HK","HM","HN","HR","HT","HU","ID",
                           "IE","IL","IM","IN","IO","IQ","IR","IS","IT","JE",
                           "JM","JO","JP","KE","KG","KH","KI","KM","KN","KP",
                           "KR","KW","KY","KZ","LA","LB","LC","LI","LK","LR",
                           "LS","LT","LU","LV","LY","MA","MC","MD","ME","MG",
                           "MH","MK","ML","MM","MN","MO","MP","MQ","MR","MS",
                           "MT","MU","MV","MW","MX","MY","MZ","NA","NC","NE",
                           "NF","NG","NI","NL","NO","NP","NR","NU","NZ","OM",
                           "PA","PE","PF","PG","PH","PK","PL","PM","PN","PR",
                           "PS","PT","PW","PY","QA","RE","RO","RS","RU","RW",
                           "SA","SB","SC","SD","SE","SG","SH","SI","SJ","SK",
                           "SL","SM","SN","SO","SR","ST","SU","SV","SY","SZ",
                           "TC","TD","TF","TG","TH","TJ","TK","TL","TM","TN",
                           "TO","TP","TR","TT","TV","TW","TZ","UA","UG","UK",
                           "US","UY","UZ","VA","VC","VE","VG","VI","VN","VU",
                           "WF","WS","YE","YT","YU","ZA","ZM","ZW"
                    ];
   
   for(i = 0; i < validTLDs.length; i++){
      if(validTLDs[i] == tld){
         return [true, "OK"];
      }
   }
   
   for(i = 0; i < validCountryTLDs.length; i++){
      if(validCountryTLDs[i] == tld){
         return [true, "OK"];
      }
   }
   
   return [false, "invalid TLD (iana.org)"];
}
