//$Id$
package org.jboss.test.faces.stub.servlet;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Enumeration;
import java.util.EventListener;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.servlet.Filter;
import javax.servlet.FilterRegistration;
import javax.servlet.FilterRegistration.Dynamic;
import javax.servlet.RequestDispatcher;
import javax.servlet.Servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import javax.servlet.SessionCookieConfig;
import javax.servlet.SessionTrackingMode;
import javax.servlet.descriptor.JspConfigDescriptor;

import org.jboss.test.faces.stub.util.IteratorEnumeration;

public class StubServletContext implements ServletContext
{
   private Map<String, String> initParameters = new HashMap<String, String>();
   private Map<String, Object> attributes = new HashMap<String, Object>();
   private File webappRoot;
   private File webInfRoot;
   private File webInfClassesRoot;

   public StubServletContext()
   {
      try
      {
         URL webxml = getClass().getResource("/WEB-INF/web.xml");
         if (webxml != null)
         {
            webInfRoot = new File(webxml.toURI()).getParentFile();
            if (webInfRoot != null)
            {
               webInfClassesRoot = new File(webInfRoot.getParentFile().getPath() + "/classes");
               webappRoot = webInfRoot.getParentFile();
            }
            // call processing of context parameters
            processContextParameters(webxml);
         }
         else
         {
            webappRoot = new File(getClass().getResource("/.").toURI());
         }
      }
      catch (URISyntaxException e)
      {
         System.out.println("Unable to find web.xml:" + e.getMessage());
      }
   }

   private void processContextParameters(URL webXML)
   {
      /*
      try
      {
      Element root = XML.getRootElementSafely(webXML.openStream());
      for (Element element : (List<Element>) root.elements("context-param"))
      {
      getInitParameters().put(element.elementText("param-name"), element.elementText("param-value"));
      }
      }
      catch (IOException e) 
      {
      throw new RuntimeException("Error parsing web.xml", e);
      }
      catch (DocumentException e)
      {
      throw new RuntimeException("Error parsing web.xml", e);
      }
       */
   }

   public Map<String, String> getInitParameters()
   {
      return initParameters;
   }

   public Map<String, Object> getAttributes()
   {
      return attributes;
   }

   public ServletContext getContext(String name)
   {
      return this;
   }

   public int getMajorVersion()
   {
      return 2;
   }

   public int getMinorVersion()
   {
      return 4;
   }

   public String getMimeType(String arg0)
   {
      return null;
   }

   public Set getResourcePaths(String name)
   {
      Enumeration<URL> enumeration = null;
      try
      {
         enumeration = getClass().getClassLoader().getResources("WEB-INF");
      }
      catch (IOException e)
      {
         throw new RuntimeException("Error finding webroot.", e);
      }
      Set<String> result = new HashSet<String>();
      while (enumeration.hasMoreElements())
      {
         URL url = enumeration.nextElement();
         File rootFile = new File(url.getPath()).getParentFile();
         File newFile = new File(rootFile.getPath() + name);
         File[] files = newFile.listFiles();
         if (files != null)
         {
            addPaths(result, files, rootFile.getPath());
         }
      }
      return result;
   }

   private static void addPaths(Set<String> result, File[] files, String rootPath)
   {
      for (File file : files)
      {
         String filePath = file.getPath().substring(rootPath.length()).replace('\\', '/');
         if (file.isDirectory())
         {
            result.add(filePath + "/");
         }
         else
         {
            result.add(filePath);
         }
      }
   }

   /**
    * Get the URL for a particular resource that is relative to the web app root
    * directory.
    * 
    * @param name The name of the resource to get
    * @return The resource, or null if resource not found
    * @throws MalformedURLException If the URL is invalid
    */
   public URL getResource(String name) throws MalformedURLException
   {
      File file = getFile(name, webappRoot);

      if (file == null)
      {
         file = getFile(name, webInfRoot);
      }

      if (file == null)
      {
         file = getFile(name, webInfClassesRoot);
      }

      if (file != null)
      {
         return file.toURI().toURL();
      }
      else
      {
         return null;
      }
   }

   private static File getFile(String name, File root)
   {
      if (root == null)
      {
         return null;
      }

      if (name.startsWith("/"))
      {
         name = name.substring(1);
      }

      File f = new File(root, name);
      if (!f.exists())
      {
         return null;
      }
      else
      {
         return f;
      }
   }

   public InputStream getResourceAsStream(String name)
   {
      return getClass().getResourceAsStream(name);
   }

   public RequestDispatcher getRequestDispatcher(String url)
   {
      throw new UnsupportedOperationException();
   }

   public RequestDispatcher getNamedDispatcher(String name)
   {
      throw new UnsupportedOperationException();
   }

   public Servlet getServlet(String name) throws ServletException
   {
      throw new UnsupportedOperationException();
   }

   public Enumeration getServlets()
   {
      return null;
   }

   public Enumeration getServletNames()
   {
      return null;
   }

   public void log(String msg)
   {
   }

   public void log(Exception ex, String msg)
   {
   }

   public void log(String msg, Throwable ex)
   {
   }

   public String getRealPath(String relativePath)
   {
      if (webappRoot != null)
      {
         return webappRoot.getAbsolutePath() + relativePath;
      }
      else
      {
         return relativePath;
      }
   }

   public String getServerInfo()
   {
      return null;
   }

   public String getInitParameter(String param)
   {
      return initParameters.get(param);
   }

   public Enumeration getInitParameterNames()
   {
      return new IteratorEnumeration(initParameters.keySet().iterator());
   }

   public Object getAttribute(String att)
   {
      return attributes.get(att);
   }

   public Enumeration getAttributeNames()
   {
      return new IteratorEnumeration(attributes.keySet().iterator());
   }

   public void setAttribute(String att, Object value)
   {
      if (value == null)
      {
         attributes.remove(value);
      }
      else
      {
         attributes.put(att, value);
      }
   }

   public void removeAttribute(String att)
   {
      attributes.remove(att);
   }

   public String getServletContextName()
   {
      return "Mock";
   }

   public String getContextPath()
   {
      return null;
   }

public Dynamic addFilter(String arg0, String arg1) {
    // TODO Auto-generated method stub
    return null;
}

public Dynamic addFilter(String arg0, Filter arg1) {
    // TODO Auto-generated method stub
    return null;
}

public Dynamic addFilter(String arg0, Class<? extends Filter> arg1) {
    // TODO Auto-generated method stub
    return null;
}

public void addListener(String arg0) {
    // TODO Auto-generated method stub
    
}

public <T extends EventListener> void addListener(T arg0) {
    // TODO Auto-generated method stub
    
}

public void addListener(Class<? extends EventListener> arg0) {
    // TODO Auto-generated method stub
    
}

public javax.servlet.ServletRegistration.Dynamic addServlet(String arg0,
        String arg1) {
    // TODO Auto-generated method stub
    return null;
}

public javax.servlet.ServletRegistration.Dynamic addServlet(String arg0,
        Servlet arg1) {
    // TODO Auto-generated method stub
    return null;
}

public javax.servlet.ServletRegistration.Dynamic addServlet(String arg0,
        Class<? extends Servlet> arg1) {
    // TODO Auto-generated method stub
    return null;
}

public <T extends Filter> T createFilter(Class<T> arg0) throws ServletException {
    // TODO Auto-generated method stub
    return null;
}

public <T extends EventListener> T createListener(Class<T> arg0)
        throws ServletException {
    // TODO Auto-generated method stub
    return null;
}

public <T extends Servlet> T createServlet(Class<T> arg0)
        throws ServletException {
    // TODO Auto-generated method stub
    return null;
}

public void declareRoles(String... arg0) {
    // TODO Auto-generated method stub
    
}

public ClassLoader getClassLoader() {
    // TODO Auto-generated method stub
    return null;
}

public Set<SessionTrackingMode> getDefaultSessionTrackingModes() {
    // TODO Auto-generated method stub
    return null;
}

public int getEffectiveMajorVersion() {
    // TODO Auto-generated method stub
    return 0;
}

public int getEffectiveMinorVersion() {
    // TODO Auto-generated method stub
    return 0;
}

public Set<SessionTrackingMode> getEffectiveSessionTrackingModes() {
    // TODO Auto-generated method stub
    return null;
}

public FilterRegistration getFilterRegistration(String arg0) {
    // TODO Auto-generated method stub
    return null;
}

public Map<String, ? extends FilterRegistration> getFilterRegistrations() {
    // TODO Auto-generated method stub
    return null;
}

public JspConfigDescriptor getJspConfigDescriptor() {
    // TODO Auto-generated method stub
    return null;
}

public ServletRegistration getServletRegistration(String arg0) {
    // TODO Auto-generated method stub
    return null;
}

public Map<String, ? extends ServletRegistration> getServletRegistrations() {
    // TODO Auto-generated method stub
    return null;
}

public SessionCookieConfig getSessionCookieConfig() {
    // TODO Auto-generated method stub
    return null;
}

public boolean setInitParameter(String arg0, String arg1) {
    // TODO Auto-generated method stub
    return false;
}

public void setSessionTrackingModes(Set<SessionTrackingMode> arg0) {
    // TODO Auto-generated method stub
    
}
}
