package hirondelle.fish.test.doubles;

import java.io.FileNotFoundException;
import java.util.*;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;

/**
 Fake implementation of {@link ServletConfig}, used only for testing outside 
 of the regular runtime environment.
 
 <P>This class fakes the data in <tt>web.xml</tt>, and returns a 
 {@link FakeServletContext}. The <tt>ServletContext</tt> is needed for scanning in 
 your <tt>.sql</tt> files. As well, it references {@link FakeConnectionSrc}.
 
 <P>The main use case for this class is to be passed to
 {@link hirondelle.web4j.Controller#init(javax.servlet.ServletConfig)}. 
 
 <P>This implementation hard-codes its data. Other implementations  
 might read data from another source - perhaps a properties file, or perhaps 
 <tt>web.xml</tt> itself.
*/
public class FakeServletConfig implements ServletConfig {
  
  /**  Simple test harness. Emits the init param names and values.  */
  private static void main(String... aArgs) throws FileNotFoundException {
    log("Starting.");
    FakeServletConfig fake = new FakeServletConfig();
    Enumeration names = fake.getInitParameterNames();
    while( names.hasMoreElements() ){
      Object name = names.nextElement();
      String value = fake.getInitParameter(name.toString());
      log(name + "=" + value);
    }
    log("Done.");
  }
  
  /** Value :  {@value}. */
  public static final String SERVLET_NAME = "Fake Testing Servlet";
  
  /** Constructor. Uses a {@link FakeServletContext}, and hard-codes its init params. */
  public FakeServletConfig() throws FileNotFoundException {
    fFakeServletContext = new FakeServletContext();
    fInitParams = buildFakeData();
  }
  
  public String getInitParameter(String aParamName) {
    return fInitParams.get(aParamName);
  }
  
  public Enumeration getInitParameterNames() {
    return Collections.enumeration(fInitParams.keySet());
  }
  
  /** Returns a {@link FakeServletContext}. */
  public ServletContext getServletContext() {
    return fFakeServletContext;
  }

  /** Returns {@value #SERVLET_NAME}. */
  public String getServletName() {
    return SERVLET_NAME;
  }
  
  // PRIVATE //
  private Map<String, String> fInitParams;
  private ServletContext fFakeServletContext;
  
  private Map<String, String> buildFakeData(){
    Map<String, String> result = new LinkedHashMap<String, String>();
    
    result.put("Webmaster", "BLAH@BLAH.COM");
    result.put("EmailInSeparateThread", "YES");
    result.put("LoggingDirectory", "C:\\log\\fish\\");
    result.put("LoggingLevels", "hirondelle.fish.level=FINE, hirondelle.web4j.level=FINE");
    result.put("ImplicitMappingRemoveBasePackage", "hirondelle.fish");
    result.put("TroubleTicketMailingList", "BLAH@BLAH.COM, BLAH@BLAH.COM");
    result.put("MinimumIntervalBetweenTroubleTickets", "30");
    result.put("PoorPerformanceThreshold", "20");
    result.put("MaxHttpRequestSize", "51200");
    result.put("MaxFileUploadRequestSize", "1048576");
    result.put("MaxRequestParamValueSize", "51200");
    result.put("SpamDetectionInFirewall", "OFF");
    result.put("FullyValidateFileUploads", "ON");
    result.put("CharacterEncoding", "UTF-8");
    result.put("DefaultLocale", "en");
    result.put("DefaultUserTimeZone", "UTC");
    result.put("TimeZoneHint", "NONE");
    result.put("DecimalStyle", "HALF_EVEN,2");
    result.put("DecimalSeparator", "PERIOD");
    result.put("BigDecimalDisplayFormat", "#,##0.00");
    result.put("BooleanTrueDisplayFormat", "<input type='checkbox' name='blah' value='blah' checked readonly notab>");
    result.put("BooleanFalseDisplayFormat", "<input type='checkbox' name='blah' value='blah' readonly notab>");
    result.put("EmptyOrNullDisplayFormat", "-");
    result.put("IntegerDisplayFormat", "#,###");
    result.put("IgnorableParamValue", "");
    result.put("IsSQLPrecompilationAttempted", "true");
    result.put("MaxRows", "300");
    result.put("FetchSize", "25");
    result.put("HasAutoGeneratedKeys", "true");
    result.put("ErrorCodeForDuplicateKey", "1062");
    result.put("SqlFetcherDefaultTxIsolationLevel", "DATABASE_DEFAULT");
    result.put("SqlEditorDefaultTxIsolationLevel", "DATABASE_DEFAULT");
    
    //Note the fake implementation of ConnectionSource, along with its required data
    result.put("ImplementationFor.hirondelle.web4j.database.ConnectionSource", "hirondelle.fish.test.doubles.FakeConnectionSrc");
    result.put("DefaultDbConnectionString", "jdbc:mysql://localhost:3306/fish");
    result.put("TranslationDbConnectionString", "jdbc:mysql://localhost:3306/fish_translation");
    result.put("AccessControlDbConnectionString", "jdbc:mysql://localhost:3306/fish_access");
    
    return result;
  }
  
  private static void log(Object aObject){
    System.out.println(String.valueOf(aObject));
  }
}