/*
 * 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 flex.messaging.io.amfx;

import flex.messaging.MessageException;
import flex.messaging.io.amf.ASObject;
import flex.messaging.io.amf.ActionMessage;
import flex.messaging.io.amf.MessageBody;
import flex.messaging.io.amf.MessageHeader;
import flex.messaging.io.SerializationContext;

import java.util.Date;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.ArrayList;
import java.lang.reflect.Array;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.apache.xpath.CachedXPathAPI;

/**
 * Verifies that a deserialized ActionMessage
 * from an AMFX request matches the expected value.
 */
public abstract class DeserializationConfirmation
{
    public static final int EXPECTED_VERSION = 3;

    private IdentityHashMap knownObjects;

    protected SerializationContext context;

    protected DeserializationConfirmation()
    {
    }

    private void init()
    {
        knownObjects = new IdentityHashMap(64);
    }

    public void setContext(SerializationContext context)
    {
        this.context = context;
    }

    public boolean isNegativeTest()
    {
        return false;
    }

    public boolean successMatches(ActionMessage m)
    {
        init();

        try
        {
            boolean match = messagesMatch(m, getExpectedMessage());
            return match;
        }
        catch (Exception ex)
        {
            return false;
        }
    }

    public abstract ActionMessage getExpectedMessage();

    public boolean negativeMatches(ActionMessage m)
    {
        init();

        MessageException ex = null;
        MessageBody body = m.getBody(0);

        if ((body == null) || (body.getData() == null) || (!(body.getData() instanceof MessageException)))
            return false;
        else
            ex = (MessageException)body.getData();

        String message1 = ex.getMessage();
        String message2 = getExpectedException().getMessage();

        if (message1 == null && message2 == null)
            return true;

        if ((message1 == null && message2 != null) || (message1 != null && message2 == null))
            return false;

        return message1.equalsIgnoreCase(message2);
    }

    public abstract MessageException getExpectedException();


    protected boolean headersMatch(MessageHeader header1, MessageHeader header2)
    {
        if ((header1 == null && header2 != null) || (header1 != null && header2 == null))
            return false;

        if (!header1.getName().equalsIgnoreCase(header2.getName()))
            return false;

        if (header1.getMustUnderstand() != header2.getMustUnderstand())
            return false;

        Object data1 = header1.getData();
        Object data2 = header2.getData();

        if (!headerValuesMatch(data1, data2))
            return false;

        return true;
    }

    protected boolean headerValuesMatch(Object o1, Object o2)
    {
        return valuesMatch(o1, o2);
    }

    protected boolean bodiesMatch(MessageBody body1, MessageBody body2)
    {
        if ((body1 == null && body2 != null) || (body1 != null && body2 == null))
            return false;

        if (!body1.getTargetURI().equalsIgnoreCase(body2.getTargetURI()))
            return false;

        if (!body1.getResponseURI().equalsIgnoreCase(body2.getResponseURI()))
            return false;

        Object data1 = body1.getData();
        Object data2 = body2.getData();

        if (!bodyValuesMatch(data1, data2))
            return false;

        return true;
    }

    protected boolean bodyValuesMatch(Object o1, Object o2)
    {
        return valuesMatch(o1, o2);
    }

    protected boolean messagesMatch(ActionMessage m1, ActionMessage m2)
    {
        if ((m1 == null && m2 != null) || (m2 == null && m1 != null))
            return false;

        if (m1.getVersion() != m2.getVersion())
            return false;

        int headerCount1 = m1.getHeaderCount();
        int headerCount2 = m2.getHeaderCount();

        if (headerCount1 != headerCount2)
            return false;

        for (int i = 0; i < headerCount1; i++)
        {
            MessageHeader header1 = m1.getHeader(i);
            MessageHeader header2 = m2.getHeader(i);
            if (!headersMatch(header1, header2))
                return false;
        }

        int bodyCount1 = m1.getBodyCount();
        int bodyCount2 = m2.getBodyCount();

        if (bodyCount1 != bodyCount2)
            return false;

        for (int i = 0; i < bodyCount1; i++)
        {
            MessageBody body1 = m1.getBody(i);
            MessageBody body2 = m2.getBody(i);

            if (!bodiesMatch(body1, body2))
                return false;
        }

        return true;
    }

    protected boolean valuesMatch(Object o1, Object o2)
    {
        if (o1 == null && o2 == null)
            return true;

        if (o1 instanceof ASObject)
        {
            return objectsMatch((ASObject)o1, (Map)o2);
        }
        else if (o1 instanceof Map)
        {
            return mapsMatch((Map)o1, (Map)o2);
        }
        else if (o1 instanceof List)
        {
            return listsMatch((List)o1, (List)o2);
        }
        else if (o1.getClass().isArray())
        {
            return arraysMatch(o1, o2);
        }
        else if (o1 instanceof Document)
        {
            return documentsMatch((Document)o1, (Document)o2);
        }
        else if (o1 != null)
        {
            if (hasComplexChildren(o1))
            {
                // We avoid checking a complex/custom types twice in
                // case of circular dependencies
                Object known = knownObjects.get(o1);
                if (known != null)
                {
                    return true;
                }
                else
                {
                    knownObjects.put(o1, o2);
                }
            }

            // Special case Double and Integer
            if (o1 instanceof Double && o2 instanceof Integer)
                return new Integer(((Double)o1).intValue()).equals(o2);

            return o1.equals(o2);
        }

        return false;
    }

    protected boolean documentsMatch(Document doc1, Document doc2)
    {
        boolean match = false;

        try
        {
            CachedXPathAPI xpath1 = new CachedXPathAPI();
            CachedXPathAPI xpath2 = new CachedXPathAPI();
            Node root1 = xpath1.selectSingleNode(doc1, "/");
            Node root2 = xpath2.selectSingleNode(doc2, "/");

            if (!nodesMatch(xpath1, root1, xpath2, root2))
            {
                return false;
            }

            match = true;
        }
        catch (Throwable t)
        {
            throw new MessageException("Error comparing XML Documents: " + t.getMessage(), t);
        }

        return match;

    }

    protected boolean nodesMatch(CachedXPathAPI xpath1, Node node1, CachedXPathAPI xpath2, Node node2)
    {
        boolean match = false;

        try
        {
            NodeList list1 = xpath1.selectNodeList(node1, "*");
            NodeList list2 = xpath2.selectNodeList(node2, "*");

            if (list1.getLength() == list2.getLength())
            {
                for (int i = 0; i < list1.getLength(); i++)
                {
                    Node n1 = list1.item(i);
                    Node n2 = list2.item(i);

                    NodeList attributes1 = xpath1.selectNodeList(n1, "@*");
                    NodeList attributes2 = xpath2.selectNodeList(n2, "@*");

                    if (!attributesMatch(attributes1, attributes2))
                    {
                        return false;
                    }

                    if (!nodesMatch(xpath1, n1, xpath2, n2))
                    {
                        return false;
                    }
                }

                match = true;
            }
        }
        catch (Throwable t)
        {
            throw new MessageException("Error comparing XML nodes: " + t.getMessage(), t);
        }

        return match;

    }

    protected boolean attributesMatch(NodeList attributes1, NodeList attributes2)
    {
        if (attributes1 == null && attributes2 == null)
            return true;

        boolean match = false;

        if (attributes1.getLength() == attributes2.getLength())
        {
            for (int i = 0; i < attributes1.getLength(); i++)
            {
                Node a1 = attributes1.item(i);
                Node a2 = attributes2.item(i);

                if (!stringValuesMatch(a1.getNodeName(), a2.getNodeName()))
                    return false;

                if (!stringValuesMatch(a1.getNodeValue(), a2.getNodeValue()))
                    return false;
            }

            match = true;
        }

        return match;
    }


    protected boolean objectsMatch(ASObject aso1, Map aso2)
    {
        String type1 = aso1.getType();

        // We may have an anonymous ASObject and an ECMA Array
        // which get serialized in the same way, i.e. a Map,
        // so we ignore this difference
        if (type1 != null)
        {
            String type2 = ((ASObject)aso2).getType();

            if (!stringValuesMatch(type1, type2))
                return false;
        }

        return mapsMatch(aso1, aso2);
    }

    protected boolean stringValuesMatch(String str1, String str2)
    {
        if (str1 == null && str2 == null)
            return true;

        if (str1 != null && !str1.equals(str2))
            return false;

        return true;
    }

    protected boolean mapsMatch(Map map1, Map map2)
    {
        if (map1.size() != map2.size())
            return false;

        // We avoid checking a Map twice in case
        // of circular dependencies
        Object known = knownObjects.get(map1);
        if (known != null)
        {
            return true;
        }
        else
        {
            knownObjects.put(map1, map2);
        }

        Iterator it = map1.keySet().iterator();
        while (it.hasNext())
        {
            Object next = it.next();
            if (next instanceof String)
            {
                String key = (String)next;
                Object val1 = map1.get(key);
                Object val2 = map2.get(key);

                if (!valuesMatch(val1, val2))
                    return false;
            }
            else
            {
                return false;
            }
        }

        return true;
    }

    protected boolean listsMatch(List list1, List list2)
    {
        if (list1.size() != list2.size())
            return false;

        // We avoid checking a List twice in case
        // of circular dependencies
        Object known = knownObjects.get(list1);
        if (known != null)
        {
            return true;
        }
        else
        {
            knownObjects.put(list1, list2);
        }

        for (int i = 0; i < list1.size(); i++)
        {
            Object o1 = list1.get(i);
            Object o2 = list2.get(i);

            if (!valuesMatch(o1, o2))
                return false;
        }

        return true;
    }

    protected boolean arraysMatch(Object array1, Object array2)
    {
        int len1 = Array.getLength(array1);
        int len2 = Array.getLength(array2);

        if (len1 != len2)
            return false;

        // We avoid checking an Array twice in case
        // of circular dependencies
        Object known = knownObjects.get(array1);
        if (known != null)
        {
            return true;
        }
        else
        {
            knownObjects.put(array1, array2);
        }

        for (int i = 0; i < len1; i++)
        {
            Object o1 = Array.get(array1, i);
            Object o2 = Array.get(array2, i);

            if (!valuesMatch(o1, o2))
                return false;
        }

        return true;
    }

    protected void addToList(Object list, int index, Object value)
    {
        if (list instanceof List)
            ((List)list).add(value);
        else if (list.getClass().isArray())
            Array.set(list, index, value);
    }

    protected Object getFromList(Object list, int index)
    {
        if (list instanceof List)
            return ((List)list).get(index);
        else
            return Array.get(list, index);
    }

    protected Object createList(int length)
    {
        if (context.legacyCollection)
            return new ArrayList(length);
        else
            return new Object[length];
    }

    private static boolean hasComplexChildren(Object o)
    {
        if (o instanceof String
                || o instanceof Boolean
                || o instanceof Number
                || o instanceof Character
                || o instanceof Date)
        {
            return false;
        }

        return true;
    }

}
