/*
 * 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.IOException;
import java.io.Writer;
import javax.faces.component.UIComponent;
import javax.faces.context.ResponseWriter;

/**
 * <p>Mock implementation of <code>javax.faces.context.ResponseWriter</code>.</p>
 * 
 * @since 1.0.0
 */
public class MockResponseWriter extends ResponseWriter
{

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

    public MockResponseWriter(Writer writer)
    {
        this.writer = writer;
        this.contentType = "text/html";
        this.characterEncoding = "UTF-8";
    }

    /**
     * <p>Construct an instance wrapping the specified writer.</p>
     *
     * @param writer Writer we are wrapping
     * @param contentType Content type to be created
     * @param characterEncoding Character encoding of this response
     */
    public MockResponseWriter(Writer writer, String contentType,
            String characterEncoding)
    {
        this.writer = writer;
        this.contentType = contentType;
        this.characterEncoding = characterEncoding;
    }

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

    private String characterEncoding = null;
    private String contentType = "text/html";
    private boolean open = false; // Is an element currently open?
    private UIComponent component;
    private Writer writer = null;

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

    /**
     * <p>Return the <code>Writer</code> that we are wrapping.</p>
     */
    public Writer getWriter()
    {
        return this.writer;
    }

    // -------------------------------------------------- ResponseWriter Methods

    /** {@inheritDoc} */
    public ResponseWriter cloneWithWriter(Writer writer)
    {
        return new MockResponseWriter(writer, contentType, characterEncoding);
    }

    /** {@inheritDoc} */
    public void endDocument() throws IOException
    {
        finish();
        writer.flush();
    }

    /** {@inheritDoc} */
    public void endElement(String name) throws IOException
    {
        if (open)
        {
            writer.write("/");
            finish();
        }
        else
        {
            writer.write("</");
            writer.write(name);
            writer.write(">");
        }
        component = null;
    }

    /** {@inheritDoc} */
    public String getCharacterEncoding()
    {
        return this.characterEncoding;
    }

    /** {@inheritDoc} */
    public String getContentType()
    {
        return this.contentType;
    }

    /** {@inheritDoc} */
    public void flush() throws IOException
    {
        finish();
    }

    /** {@inheritDoc} */
    public void startDocument() throws IOException
    {
        // Do nothing
    }

    /** {@inheritDoc} */
    public void startElement(String name, UIComponent component)
            throws IOException
    {
        if (name == null)
        {
            throw new NullPointerException();
        }
        finish();
        writer.write('<');
        writer.write(name);
        open = true;
        this.component = component;
    }

    /** {@inheritDoc} */
    public void writeAttribute(String name, Object value, String property)
            throws IOException
    {
        if (name == null)
        {
            throw new NullPointerException();
        }
        if (!open)
        {
            throw new IllegalStateException();
        }
        String attribute = findValue(value, property);
        if (attribute != null)
        {
            writer.write(" ");
            writer.write(name);
            writer.write("=\"");
            string(attribute);

            writer.write("\"");
        }
    }

    /** {@inheritDoc} */
    public void writeComment(Object comment) throws IOException
    {
        if (comment == null)
        {
            throw new NullPointerException();
        }
        finish();
        writer.write("<!-- ");
        if (comment instanceof String)
        {
            writer.write((String) comment);
        }
        else
        {
            writer.write(comment.toString());
        }
        writer.write(" -->");
    }

    /** {@inheritDoc} */
    public void writeText(Object text, String property) throws IOException
    {
        if (text == null)
        {
            throw new NullPointerException();
        }
        finish();
        String value = findValue(text, property);
        if (value != null)
        {
            string(value);
        }

    }

    /** {@inheritDoc} */
    public void writeText(char[] text, int off, int len) throws IOException
    {
        if (text == null)
        {
            throw new NullPointerException();
        }
        if ((off < 0) || (off > text.length) || (len < 0)
                || (len > text.length))
        {
            throw new IndexOutOfBoundsException();
        }
        finish();
        string(text, off, len);
    }

    /** {@inheritDoc} */
    public void writeURIAttribute(String name, Object value, String property)
            throws IOException
    {
        if (name == null)
        {
            throw new NullPointerException();
        }
        if (!open)
        {
            throw new IllegalStateException();
        }
        String attribute = findValue(value, property);
        if (attribute != null)
        {
            writer.write(" ");
            writer.write(name);
            writer.write("=\"");

            string(attribute);
            writer.write("\"");
        }
    }

    // ---------------------------------------------------------- Writer Methods

    /** {@inheritDoc} */
    public void close() throws IOException
    {
        finish();
        writer.close();
    }

    /** {@inheritDoc} */
    public void write(char[] cbuf, int off, int len) throws IOException
    {
        finish();
        writer.write(cbuf, off, len);
    }

    // --------------------------------------------------------- Support Methods

    /**
     * <p>Write the specified character, filtering if necessary.</p>
     *
     * @param ch Character to be written
     *
     * @exception IOException if an input/output error occurs
     */
    private void character(char ch) throws IOException
    {

        if (ch <= 0xff)
        {
            // In single byte characters, replace only the five
            // characters for which well-known entities exist in XML
            if (ch == 0x22)
            {
                writer.write("&quot;");
            }
            else if (ch == 0x26)
            {
                writer.write("&amp;");
            }
            else if (ch == 0x27)
            {
                writer.write("&apos;");
            }
            else if (ch == 0x3C)
            {
                writer.write("&lt;");
            }
            else if (ch == 0X3E)
            {
                writer.write("&gt;");
            }
            else
            {
                writer.write(ch);
            }
        }
        else
        {
            if (substitution())
            {
                numeric(writer, ch);
            }
            else
            {
                writer.write(ch);
            }
        }

    }

    /**
     * <p>Close any element that is currently open.</p>
     *
     * @exception IOException if an input/output error occurs
     */
    private void finish() throws IOException
    {

        if (open)
        {
            writer.write(">");
            open = false;
        }

    }

    /**
     * <p>Write a numeric character reference for specified character
     * to the specfied writer.</p>
     *
     * @param writer Writer we are writing to
     * @param ch Character to be translated and appended
     *
     * @exception IOException if an input/output error occurs
     */
    private void numeric(Writer writer, char ch) throws IOException
    {

        writer.write("&#");
        writer.write(String.valueOf(ch));
        writer.write(";");

    }

    /**
     * <p>Write the specified characters (after performing suitable
     * replacement of characters by corresponding entities).</p>
     *
     * @param text Character array containing text to be written
     * @param off Starting offset (zero relative)
     * @param len Number of characters to be written
     *
     * @exception IOException if an input/output error occurs
     */
    private void string(char[] text, int off, int len) throws IOException
    {

        // Process the specified characters
        for (int i = off; i < (off + len); i++)
        {
            character(text[i]);
        }

    }

    /**
     * <p>Write the specified string (after performing suitable
     * replacement of characters by corresponding entities).</p>
     *
     * @param s String to be filtered and written
     *
     * @exception IOException if an input/output error occurs
     */
    private void string(String s) throws IOException
    {
        for (int i = 0; i < s.length(); i++)
        {
            character(s.charAt(i));
        }

    }

    /**
     * <p>Return true if entity substitution should be performed on double
     * byte character values.</p>
     */
    private boolean substitution()
    {

        return !("UTF-8".equals(characterEncoding) || "UTF-16"
                .equals(characterEncoding));

    }

    private String findValue(final Object value, final String property)
    {
        if (value != null)
        {
            return value instanceof String ? (String) value : value.toString();
        }
        else if (property != null)
        {
            if (component != null)
            {
                final Object object = component.getAttributes().get(property);
                if (object != null)
                {
                    return object instanceof String ? (String) object : object
                            .toString();
                }
                else
                {
                    return null;
                }
            }

        }
        return null;
    }

}
