/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.apache.myfaces.test.mock;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.security.Principal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
import java.util.Vector;
import javax.servlet.AsyncContext;
import javax.servlet.DispatcherType;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletRequest;
import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.Part;

/**
 * <p>Mock implementation of <code>HttpServletContext</code>.</p>
 *
 * $Id$
 * @since 1.0.0
 */
public class MockHttpServletRequest implements HttpServletRequest
{

    // ------------------------------------------------------------ Constructors

    public MockHttpServletRequest()
    {

        super();

    }

    public MockHttpServletRequest(HttpSession session)
    {

        super();
        setHttpSession(session);

    }

    public MockHttpServletRequest(String contextPath, String servletPath,
            String pathInfo, String queryString)
    {

        super();
        setPathElements(contextPath, servletPath, pathInfo, queryString);

    }

    public MockHttpServletRequest(String contextPath, String servletPath,
            String pathInfo, String queryString, HttpSession session)
    {

        super();
        setPathElements(contextPath, servletPath, pathInfo, queryString);
        setHttpSession(session);

    }

    // ----------------------------------------------------- Mock Object Methods

    /**
     * <p>Add a new listener instance that should be notified about
     * attribute changes.</p>
     *
     * @param listener The new listener to register
     */
    public void addAttributeListener(ServletRequestAttributeListener listener)
    {
        attributeListeners.add(listener);
    }

    /**
     * <p>Add a date-valued header for this request.</p>
     *
     * @param name Header name
     * @param value Header value
     */
    public void addDateHeader(String name, long value)
    {

        headers.add(name + ": " + formatDate(value));

    }

    /**
     * <p>Add a String-valued header for this request.</p>
     *
     * @param name Header name
     * @param value Header value
     */
    public void addHeader(String name, String value)
    {

        headers.add(name + ": " + value);

    }

    /**
     * <p>Add an integer-valued header for this request.</p>
     *
     * @param name Header name
     * @param value Header value
     */
    public void addIntHeader(String name, int value)
    {

        headers.add(name + ": " + value);

    }

    /**
     * <p>Add a request parameter for this request.</p>
     *
     * @param name Parameter name
     * @param value Parameter value
     */
    public void addParameter(String name, String value)
    {

        String[] values = (String[]) parameters.get(name);
        if (values == null)
        {
            String[] results = new String[] { value };
            parameters.put(name, results);
            return;
        }
        String[] results = new String[values.length + 1];
        System.arraycopy(values, 0, results, 0, values.length);
        results[values.length] = value;
        parameters.put(name, results);

    }

    public void addCookie(Cookie c)
    {
        for (int i = 0; i < cookies.size(); i++)
        {
            if (((Cookie) cookies.get(i)).getName().equals(c.getName()))
            {
                cookies.set(i, c);
                return;
            }
        }
        cookies.add(c);
    }

    /**
     * <p>Return the <code>ServletContext</code> associated with
     * this request.</p>
     */
    public ServletContext getServletContext()
    {

        return this.servletContext;

    }

    /**
     * <p>Set the <code>HttpSession</code> associated with this request.</p>
     *
     * @param session The new session
     */
    public void setHttpSession(HttpSession session)
    {

        this.session = session;

    }

    /**
     * <p>Set the <code>Locale</code> associated with this request.</p>
     *
     * @param locale The new locale
     */
    public void setLocale(Locale locale)
    {

        this.locale = locale;

    }

    /**
     * <p>Set the parsed path elements associated with this request.</p>
     *
     * @param contextPath The context path
     * @param servletPath The servlet path
     * @param pathInfo The extra path information
     * @param queryString The query string
     */
    public void setPathElements(String contextPath, String servletPath,
            String pathInfo, String queryString)
    {

        this.contextPath = contextPath;
        this.servletPath = servletPath;
        this.pathInfo = pathInfo;
        this.queryString = queryString;

    }

    /**
     * <p>Set the <code>ServletContext</code> associated with this request.</p>
     *
     * @param servletContext The new servlet context
     */
    public void setServletContext(ServletContext servletContext)
    {

        this.servletContext = servletContext;

    }

    /**
     * <p>Set the <code>Principal</code> associated with this request.</p>
     *
     * @param principal The new Principal
     */
    public void setUserPrincipal(Principal principal)
    {

        this.principal = principal;

    }
    
    public void setMethod(String method)
    {
        this.method = method;
    }
    
    protected MockWebContainer getWebContainer()
    {
        if (this.servletContext instanceof MockServletContext)
        {
            return ((MockServletContext)this.servletContext).getWebContainer();
        }
        return null;
    }
    
    /**
     * @param contextPath the contextPath to set
     */
    public void setContextPath(String contextPath)
    {
        this.contextPath = contextPath;
    }

    /**
     * @param pathInfo the pathInfo to set
     */
    public void setPathInfo(String pathInfo)
    {
        this.pathInfo = pathInfo;
    }

    /**
     * @param servletPath the servletPath to set
     */
    public void setServletPath(String servletPath)
    {
        this.servletPath = servletPath;
    }
    
    public void addUserRole(String role)
    {
        if (this.roles == null)
        {
            this.roles = new ArrayList<String>();
        }
        this.roles.add(role);
    }
        
    public void clearUserRoles()
    {
        if (this.roles == null)
        {
            return;
        }
        this.roles.clear();
    }

    // ------------------------------------------------------ Instance Variables

    private List attributeListeners = new ArrayList();
    private HashMap attributes = new HashMap();
    private String contextPath = null;
    private List headers = new ArrayList();
    private Locale locale = null;
    private HashMap parameters = new HashMap();
    private String pathInfo = null;
    private Principal principal = null;
    private String queryString = null;
    private ServletContext servletContext = null;
    private String servletPath = null;
    private HttpSession session = null;
    private String characterEncoding = null;
    private ServletInputStream inputStream = null;
    private List cookies = new ArrayList();
    private Vector locales = null;
    private String method = null;
    private List<String> roles = null;

    // ---------------------------------------------- HttpServletRequest Methods

    /** {@inheritDoc} */
    public String getAuthType()
    {

        throw new UnsupportedOperationException();

    }

    /** {@inheritDoc} */
    public String getContextPath()
    {

        return contextPath;

    }

    /** {@inheritDoc} */
    public Cookie[] getCookies()
    {

        Cookie[] array = new Cookie[cookies.size()];
        for (int i = 0; i < cookies.size(); i++)
        {
            array[i] = (Cookie) cookies.get(i);
        }
        return array;
    }

    /** {@inheritDoc} */
    public long getDateHeader(String name)
    {

        String match = name + ":";
        Iterator headers = this.headers.iterator();
        while (headers.hasNext())
        {
            String header = (String) headers.next();
            if (header.startsWith(match))
            {
                return parseDate(header.substring(match.length() + 1).trim());
            }
        }
        return (long) -1;

    }

    /** {@inheritDoc} */
    public String getHeader(String name)
    {

        String match = name + ":";
        Iterator headers = this.headers.iterator();
        while (headers.hasNext())
        {
            String header = (String) headers.next();
            if (header.startsWith(match))
            {
                return header.substring(match.length() + 1).trim();
            }
        }
        return null;

    }

    /** {@inheritDoc} */
    public Enumeration getHeaderNames()
    {

        Vector values = new Vector();
        Iterator headers = this.headers.iterator();
        while (headers.hasNext())
        {
            String header = (String) headers.next();
            int colon = header.indexOf(':');
            if (colon >= 0)
            {
                String name = header.substring(0, colon).trim();
                if (!values.contains(name))
                {
                    values.add(name);
                }
            }
        }
        return values.elements();

    }

    /** {@inheritDoc} */
    public Enumeration getHeaders(String name)
    {

        String match = name + ":";
        Vector values = new Vector();
        Iterator headers = this.headers.iterator();
        while (headers.hasNext())
        {
            String header = (String) headers.next();
            if (header.startsWith(match))
            {
                values.add(header.substring(match.length() + 1).trim());
            }
        }
        return values.elements();

    }

    /** {@inheritDoc} */
    public int getIntHeader(String name)
    {

        String match = name + ":";
        Iterator headers = this.headers.iterator();
        while (headers.hasNext())
        {
            String header = (String) headers.next();
            if (header.startsWith(match))
            {
                return Integer.parseInt(header.substring(match.length() + 1)
                        .trim());
            }
        }
        return -1;

    }

    /** {@inheritDoc} */
    public String getMethod()
    {

        return method;

    }

    /** {@inheritDoc} */
    public String getPathInfo()
    {

        return pathInfo;

    }

    /** {@inheritDoc} */
    public String getPathTranslated()
    {

        throw new UnsupportedOperationException();

    }

    /** {@inheritDoc} */
    public String getQueryString()
    {

        return queryString;

    }

    /** {@inheritDoc} */
    public String getRemoteUser()
    {

        if (principal != null)
        {
            return principal.getName();
        }
        else
        {
            return null;
        }

    }

    /** {@inheritDoc} */
    public String getRequestedSessionId()
    {

        throw new UnsupportedOperationException();

    }

    /** {@inheritDoc} */
    public String getRequestURI()
    {

        StringBuffer sb = new StringBuffer();
        if (contextPath != null)
        {
            sb.append(contextPath);
        }
        if (servletPath != null)
        {
            sb.append(servletPath);
        }
        if (pathInfo != null)
        {
            sb.append(pathInfo);
        }
        if (sb.length() > 0)
        {
            return sb.toString();
        }
        throw new UnsupportedOperationException();

    }

    /** {@inheritDoc} */
    public StringBuffer getRequestURL()
    {

        throw new UnsupportedOperationException();

    }

    /** {@inheritDoc} */
    public String getServletPath()
    {

        return (servletPath);

    }

    /** {@inheritDoc} */
    public HttpSession getSession()
    {

        return getSession(true);

    }

    /** {@inheritDoc} */
    public HttpSession getSession(boolean create)
    {

        if (create && (session == null))
        {
            this.session = new MockHttpSession(this.servletContext);
            MockWebContainer container = getWebContainer();
            if (container != null)
            {
                HttpSessionEvent se = new HttpSessionEvent(this.session);
                container.sessionCreated(se);
            }
        }
        return session;

    }

    /** {@inheritDoc} */
    public Principal getUserPrincipal()
    {

        return principal;

    }

    /** {@inheritDoc} */
    public boolean isRequestedSessionIdFromCookie()
    {

        throw new UnsupportedOperationException();

    }

    /** {@inheritDoc} */
    public boolean isRequestedSessionIdFromUrl()
    {

        throw new UnsupportedOperationException();

    }

    /** {@inheritDoc} */
    public boolean isRequestedSessionIdFromURL()
    {

        throw new UnsupportedOperationException();

    }

    /** {@inheritDoc} */
    public boolean isRequestedSessionIdValid()
    {

        throw new UnsupportedOperationException();

    }

    /** {@inheritDoc} */
    public boolean isUserInRole(String role)
    {
        return (this.roles != null) ? this.roles.contains(role) : false;
    }

    // ------------------------------------------------- ServletRequest Methods

    /** {@inheritDoc} */
    public Object getAttribute(String name)
    {

        return attributes.get(name);

    }

    /** {@inheritDoc} */
    public Enumeration getAttributeNames()
    {

        return new MockEnumeration(attributes.keySet().iterator());

    }

    /** {@inheritDoc} */
    public String getCharacterEncoding()
    {

        return characterEncoding;

    }

    /** {@inheritDoc} */
    public int getContentLength()
    {

        throw new UnsupportedOperationException();

    }

    /** {@inheritDoc} */
    public String getContentType()
    {

        throw new UnsupportedOperationException();

    }

    /** {@inheritDoc} */
    public ServletInputStream getInputStream()
    {
        return this.inputStream;
    }

    public void setInputStream(MockServletInputStream stream)
    {
        this.inputStream = stream;
    }

    /** {@inheritDoc} */
    public Locale getLocale()
    {

        return locale;

    }

    /** {@inheritDoc} */
    public Enumeration getLocales()
    {
        if (this.locales == null)
        {
            locales = new Vector(Arrays.asList(Locale.getAvailableLocales()));
        }
        return this.locales.elements();
    }

    /** {@inheritDoc} */
    public String getLocalAddr()
    {

        throw new UnsupportedOperationException();

    }

    /** {@inheritDoc} */
    public String getLocalName()
    {

        throw new UnsupportedOperationException();

    }

    /** {@inheritDoc} */
    public int getLocalPort()
    {

        throw new UnsupportedOperationException();

    }

    /** {@inheritDoc} */
    public String getParameter(String name)
    {

        String[] values = (String[]) parameters.get(name);
        if (values != null)
        {
            return values[0];
        }
        else
        {
            return null;
        }

    }

    /** {@inheritDoc} */
    public Map getParameterMap()
    {

        return parameters;

    }

    /** {@inheritDoc} */
    public Enumeration getParameterNames()
    {

        return new MockEnumeration(parameters.keySet().iterator());

    }

    /** {@inheritDoc} */
    public String[] getParameterValues(String name)
    {

        return (String[]) parameters.get(name);

    }

    /** {@inheritDoc} */
    public String getProtocol()
    {

        throw new UnsupportedOperationException();

    }

    /** {@inheritDoc} */
    public BufferedReader getReader()
    {
        if (this.inputStream != null)
        {
            try
            {
                Reader sourceReader = (this.characterEncoding != null) ? new InputStreamReader(
                        this.inputStream, this.characterEncoding)
                        : new InputStreamReader(this.inputStream);
                return new BufferedReader(sourceReader);
            }
            catch (UnsupportedEncodingException e)
            {
                throw new RuntimeException(e);
            }
        }
        else
        {
            return null;
        }
    }

    /** {@inheritDoc} */
    public String getRealPath(String path)
    {

        throw new UnsupportedOperationException();

    }

    /** {@inheritDoc} */
    public String getRemoteAddr()
    {

        // i figure testing never assumes a specific remote - so anything works
        return "1.2.3.4";

    }

    /** {@inheritDoc} */
    public String getRemoteHost()
    {

        // i figure testing never assumes a specific remote - so anything works
        return "MyfacesServer";

    }

    /** {@inheritDoc} */
    public int getRemotePort()
    {

        // i figure testing never assumes a specific remote - so anything works
        return 46123;

    }

    /** {@inheritDoc} */
    public RequestDispatcher getRequestDispatcher(String path)
    {
        return servletContext.getRequestDispatcher(path);
    }

    /** {@inheritDoc} */
    public String getScheme()
    {

        return ("http");

    }

    /** {@inheritDoc} */
    public String getServerName()
    {

        return ("localhost");

    }

    /** {@inheritDoc} */
    public int getServerPort()
    {

        return (8080);

    }

    /** {@inheritDoc} */
    public boolean isSecure()
    {

        return false;

    }

    /** {@inheritDoc} */
    public void removeAttribute(String name)
    {

        if (attributes.containsKey(name))
        {
            Object value = attributes.remove(name);
            fireAttributeRemoved(name, value);
        }

    }

    /** {@inheritDoc} */
    public void setAttribute(String name, Object value)
    {

        if (name == null)
        {
            throw new IllegalArgumentException("Attribute name cannot be null");
        }
        if (value == null)
        {
            removeAttribute(name);
            return;
        }
        if (attributes.containsKey(name))
        {
            Object oldValue = attributes.get(name);
            attributes.put(name, value);
            fireAttributeReplaced(name, oldValue);
        }
        else
        {
            attributes.put(name, value);
            fireAttributeAdded(name, value);
        }

    }

    /** {@inheritDoc} */
    public void setCharacterEncoding(String characterEncoding)
    {

        this.characterEncoding = characterEncoding;

    }

    // --------------------------------------------------------- Private Methods

    /**
     * <p>Fire an attribute added event to interested listeners.</p>
     *
     * @param key Attribute key whose value was added
     * @param value The new attribute value
     */
    private void fireAttributeAdded(String key, Object value)
    {
        if (attributeListeners.size() < 1)
        {
            return;
        }
        ServletRequestAttributeEvent event = new ServletRequestAttributeEvent(
                getServletContext(), this, key, value);
        Iterator listeners = attributeListeners.iterator();
        while (listeners.hasNext())
        {
            ServletRequestAttributeListener listener = (ServletRequestAttributeListener) listeners
                    .next();
            listener.attributeAdded(event);
        }
    }

    /**
     * <p>Fire an attribute removed event to interested listeners.</p>
     *
     * @param key Attribute key whose value was removed
     * @param value Attribute value that was removed
     */
    private void fireAttributeRemoved(String key, Object value)
    {
        if (attributeListeners.size() < 1)
        {
            return;
        }
        ServletRequestAttributeEvent event = new ServletRequestAttributeEvent(
                getServletContext(), this, key, value);
        Iterator listeners = attributeListeners.iterator();
        while (listeners.hasNext())
        {
            ServletRequestAttributeListener listener = (ServletRequestAttributeListener) listeners
                    .next();
            listener.attributeRemoved(event);
        }
    }

    /**
     * <p>Fire an attribute replaced event to interested listeners.</p>
     *
     * @param key Attribute key whose value was replaced
     * @param value The original value
     */
    private void fireAttributeReplaced(String key, Object value)
    {
        if (attributeListeners.size() < 1)
        {
            return;
        }
        ServletRequestAttributeEvent event = new ServletRequestAttributeEvent(
                getServletContext(), this, key, value);
        Iterator listeners = attributeListeners.iterator();
        while (listeners.hasNext())
        {
            ServletRequestAttributeListener listener = (ServletRequestAttributeListener) listeners
                    .next();
            listener.attributeReplaced(event);
        }
    }

    /**
     * <p>The date formatting helper we will use in <code>httpTimestamp()</code>.
     * Note that usage of this helper must be synchronized.</p>
     */
    private static SimpleDateFormat format = new SimpleDateFormat(
            "EEE, dd MMM yyyy HH:mm:ss zzz");
    static
    {
        format.setTimeZone(TimeZone.getTimeZone("GMT"));
    }

    /**
     * <p>Return a properly formatted String version of the specified
     * date/time, formatted as required by the HTTP specification.</p>
     *
     * @param date Date/time, expressed as milliseconds since the epoch
     */
    private String formatDate(long date)
    {
        return format.format(new Date(date));
    }

    /**
     * <p>Return a date/time value, parsed from the specified String.</p>
     *
     * @param date Date/time, expressed as a String
     */
    private long parseDate(String date)
    {
        try
        {
            return format.parse(date).getTime();
        }
        catch (ParseException e)
        {
            throw new IllegalArgumentException(date);
        }
    }

    public boolean authenticate(HttpServletResponse hsr) throws IOException, ServletException
    {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public Part getPart(String string) throws IOException, ServletException
    {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public Collection<Part> getParts() throws IOException, ServletException
    {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void login(String string, String string1) throws ServletException
    {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void logout() throws ServletException
    {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public AsyncContext getAsyncContext()
    {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public DispatcherType getDispatcherType()
    {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public boolean isAsyncStarted()
    {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public boolean isAsyncSupported()
    {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public AsyncContext startAsync()
    {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public AsyncContext startAsync(ServletRequest sr, ServletResponse sr1)
    {
        throw new UnsupportedOperationException("Not supported yet.");
    }

}
