package hirondelle.web4j.readconfig;

import hirondelle.web4j.util.Util;
import hirondelle.web4j.util.WebUtil;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.logging.Logger;

import hirondelle.web4j.security.UntrustedProxyForUserIdImpl;

final class ParseUntrustedProxy {
  
  Map<String, List<String>> parse(String aRawValue){
    List<String> lines = parseSeparateLines(aRawValue);
    for(String line: lines){
       parseNounsAndVerbs(line);      
    }
    fLogger.config(Util.logOnePerLine(fRestrictedOperations));
    return fRestrictedOperations;
  }

  // PRIVATE 
  private static final Logger fLogger = Util.getLogger(Config.class); // borrow a public logger, since this class is not public
  
  /** Maps nouns to corresponding verbs. */
  private Map<String, List<String>> fRestrictedOperations = new LinkedHashMap<String, List<String>>();
  
  private static final String INIT_PARAM_NAME = "UntrustedProxyForUserId";

  private List<String> parseSeparateLines(String aRawValue){
    List<String> result = new  ArrayList<String>();
    StringTokenizer parser = new StringTokenizer(aRawValue, "\n\r");
    while ( parser.hasMoreTokens() ) {
      result.add( parser.nextToken().trim() );
    }
    return result;    
  }

  private void parseNounsAndVerbs(String aLine){
    String verb = WebUtil.getFileExtension(aLine);
    int verbStart = aLine.indexOf(".");
    String noun = aLine.substring(0,verbStart);
    if( isMissing(verb)  || isMissing(noun) ){
      throw new RuntimeException(
        "This line for the " + INIT_PARAM_NAME + " setting in web.xml does not have the expected form: " + Util.quote(aLine)
      );
    }
    add(noun.trim(), verb.trim());
  }
  
  private boolean isMissing(String aText){
    return ! Util.textHasContent(aText);
  }
  
  private void add(String aNoun, String aVerb){
    if( fRestrictedOperations.containsKey(aNoun) ) {
      addAnotherVerb(aNoun, aVerb);
    }
    else {
      addNewNounAndVerb(aNoun, aVerb);
    }
  }
  
  private void addNewNounAndVerb(String aNoun, String aVerb){
    List<String> verbs = new ArrayList<String>();
    verbs.add(aVerb);
    fRestrictedOperations.put(aNoun, verbs);
  }
  
  private void addAnotherVerb(String aNoun, String aVerb){
    if( UntrustedProxyForUserIdImpl.ALL_OPERATIONS.equals(aVerb) ){
      throw new RuntimeException(
        "When you use the '" + UntrustedProxyForUserIdImpl.ALL_OPERATIONS + "' character to represent ALL operations, then only one line can be present for that item. " + 
        "In web.xml, you have a redundant setting for the init-param named " + INIT_PARAM_NAME + 
        " which needs to be removed. It is related to " +  Util.quote(aNoun) + " and " + Util.quote(aVerb)
      );
    }
    List<String> verbs = fRestrictedOperations.get(aNoun);
    verbs.add(aVerb);
  }
}
