package hirondelle.web4j;

import hirondelle.web4j.model.DateTime;
import hirondelle.web4j.model.TESTCheck;
import hirondelle.web4j.model.TESTComparePossiblyNull;
import hirondelle.web4j.model.TESTDateTime;
import hirondelle.web4j.model.TESTDateTimeFormatter;
import hirondelle.web4j.model.TESTDateTimeInterval;
import hirondelle.web4j.model.TESTDecimal;
import hirondelle.web4j.model.TESTEqualsUtil;
import hirondelle.web4j.model.TESTHashCodeUtil;
import hirondelle.web4j.model.TESTMessageSerialization;
import hirondelle.web4j.model.TESTPerformanceSnapshot;
import hirondelle.web4j.readconfig.Config;
import hirondelle.web4j.readconfig.TESTDbConfigParser;
import hirondelle.web4j.request.DateConverter;
import hirondelle.web4j.security.PermittedCharacters;
import hirondelle.web4j.security.PermittedCharactersImpl;
import hirondelle.web4j.security.TESTPermittedCharactersImpl;
import hirondelle.web4j.ui.tag.TESTFormPopulator;
import hirondelle.web4j.ui.tag.TESTHighlightCurrentPage;
import hirondelle.web4j.ui.translate.TESTText;
import hirondelle.web4j.ui.translate.TESTTranslateTextFlow;
import hirondelle.web4j.ui.translate.TESTTranslateTooltip;
import hirondelle.web4j.util.Regex;
import hirondelle.web4j.util.TESTEscapeChars;
import hirondelle.web4j.util.TESTRegex;
import hirondelle.web4j.util.TESTUtil;
import hirondelle.web4j.util.TESTWebUtil;
import hirondelle.web4j.util.TimeSource;
import hirondelle.web4j.util.TimeSourceImpl;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

/**
 Runs all <a href="http://www.junit.org">JUnit</a> tests defined for WEB4J.

 <P>This class is not useful for the application programmer.
 
 <P>Note that:
<ul>
 <li>not all classes have an associated JUnit test.
 <li>these tests may depend on details regarding the development environment, such as 
 file locations.
</ul>
*/
public final class TESTAll extends TestCase {
  
  /** Run the test cases.  */
   public static void main(String args[]) {
     //just use the default implementations
     BuildImpl.adHocImplementationAdd(TimeSource.class, TimeSourceImpl.class);
     BuildImpl.adHocImplementationAdd(PermittedCharacters.class,  PermittedCharactersImpl.class);
     //use an impl for testing
     BuildImpl.adHocImplementationAdd(DateConverter.class,  DateConverterImpl.class);
     
     String[] testCaseName = { TESTAll.class.getName()};
     
     //Select one of several types of interfaces.
     junit.textui.TestRunner.main(testCaseName);
     //junit.swingui.TestRunner.main(testCaseName);
     //junit.ui.TestRunner.main(testCaseName);
     
     //turn off logging if desired :
     //fLogger.setLevel(Level.OFF);
  }
   
  public static Test suite ( ) {
    TestSuite suite= new TestSuite("All JUnit Tests");

    //model package
    suite.addTest(new TestSuite(TESTCheck.class));
    suite.addTest(new TestSuite(TESTPerformanceSnapshot.class));
    suite.addTest(new TestSuite(TESTDecimal.class));
    suite.addTest(new TestSuite(TESTDateTime.class));
    suite.addTest(new TestSuite(TESTDateTimeFormatter.class));
    suite.addTest(new TestSuite(TESTDateTimeInterval.class));
    suite.addTest(new TestSuite(TESTComparePossiblyNull.class));
    suite.addTest(new TestSuite(TESTHashCodeUtil.class));
    suite.addTest(new TestSuite(TESTEqualsUtil.class)); 
    suite.addTest(new TestSuite(TESTMessageSerialization.class));
    
    //util package
    suite.addTest(new TestSuite(TESTRegex.class));
    suite.addTest(new TestSuite(TESTEscapeChars.class));
    suite.addTest(new TestSuite(TESTUtil.class));
    
    //webUtil package
    suite.addTest(new TestSuite(TESTWebUtil.class));
    
    //ui.tag package
    suite.addTest(new TestSuite(TESTHighlightCurrentPage.class));
    suite.addTest(new TestSuite(TESTFormPopulator.class));
    
    //ui.translate
    suite.addTest(new TestSuite(TESTTranslateTextFlow.class));
    suite.addTest(new TestSuite(TESTTranslateTooltip.class));
    suite.addTest(new TestSuite(TESTText.class));
    
    //database package
    suite.addTest(new TestSuite(TESTDbConfigParser.class));
    
    //security package 
    suite.addTest(new TestSuite(TESTPermittedCharactersImpl.class));
    
    return suite;
  }

  /** An implementation of DateConverter, used during unit testing. */
  public static final class DateConverterImpl implements DateConverter {
    //Dates:
    public String formatEyeFriendly(Date aDate, Locale aLocale, TimeZone aTimeZone) {
      SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy");
      //format.setTimeZone(aTimeZone);
      return format.format(aDate);
    }
    public Date parseHandFriendly(String aInputValue, Locale aLocale, TimeZone aTimeZone) {
      return parseDate(aInputValue, HAND_FRIENDLY_REGEX);
    }
    public Date parseEyeFriendly(String aInputValue, Locale aLocale, TimeZone aTimeZone) {
      return parseDate(aInputValue, EYE_FRIENDLY_REGEX);
    }
    //DateTimes:
    public String formatEyeFriendlyDateTime(DateTime aDateTime, Locale aLocale) {
      return aDateTime.format("MM/DD/YYYY", aLocale);
    }
    public DateTime parseEyeFriendlyDateTime(String aInputValue, Locale aLocale) {
      return parseDateTime(aInputValue, EYE_FRIENDLY_REGEX);
    }
    public DateTime parseHandFriendlyDateTime(String aInputValue, Locale aLocale) {
      return parseDateTime(aInputValue, HAND_FRIENDLY_REGEX);
    }
    private static final Pattern HAND_FRIENDLY_REGEX = 
     Pattern.compile(Regex.MONTH + Regex.DAY_OF_MONTH + "(\\d\\d\\d\\d)");
    ;
    private static final Pattern EYE_FRIENDLY_REGEX = 
      Pattern.compile(Regex.MONTH + "/" + Regex.DAY_OF_MONTH + "/" + "(\\d\\d\\d\\d)")
    ;
    private Date parseDate(String aInputValue, Pattern aRegex){
      Date result = null;
      Matcher matcher = aRegex.matcher(aInputValue);
      if( matcher.matches() ) {
        Integer month = new Integer(matcher.group(Regex.FIRST_GROUP));
        Integer day = new Integer(matcher.group(Regex.SECOND_GROUP));
        Integer year = new Integer( matcher.group(Regex.THIRD_GROUP) );
        Calendar cal = new GregorianCalendar(year.intValue(), month.intValue() - 1, day.intValue(), 0,0,0);
        result = cal.getTime();
      }
      return result;
    }
    private DateTime parseDateTime(String aInputValue, Pattern aRegex){
      DateTime result = null;
      Matcher matcher = aRegex.matcher(aInputValue);
      if( matcher.matches() ) {
        Integer month = new Integer(matcher.group(Regex.FIRST_GROUP));
        Integer day = new Integer(matcher.group(Regex.SECOND_GROUP));
        Integer year = new Integer( matcher.group(Regex.THIRD_GROUP) );
        result = DateTime.forDateOnly(year, month, day);
      }
      return result;
    }
  }
  
}
