/*
 * 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;
    }

}
