/*
 * 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.validators.ClassDeserializationValidator;
import junit.framework.TestCase;
import junit.framework.Test;
import junit.framework.TestSuite;

import java.io.IOException;
import java.io.InputStream;
import java.io.File;
import java.io.FilenameFilter;
import java.io.FileInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ByteArrayInputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;

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

/**
 * Runs through an extensive suite of deserialization
 * test cases for AMFX data types and message structures.
 *
 * The first step is to turn an XML file into an AMFX request.
 * If the request is not a negative test then it is reserialized
 * back to XML to test the serializer. Finally, the serialized
 * XML is re-deserialized back into a request and once more
 * tested.
 */
public class AmfxSerializationTest extends TestCase
{
    private String resourceBase = "/flex/messaging/io/amfx/";
    private String baseFilePath;
    private SerializationContext serializationContext;
    private AmfTrace trace;

    public AmfxSerializationTest(String name)
    {
        super(name);
    }

    public static Test suite()
    {
        return new TestSuite(AmfxSerializationTest.class);
    }

    protected void setUp() throws Exception
    {
        super.setUp();
        ClassDeserializationValidator classDeserializationValidator = new ClassDeserializationValidator();
        classDeserializationValidator.addAllowClassPattern("flex.messaging.io.amfx.testtypes.*");
        serializationContext = new SerializationContext();
        serializationContext.setDeserializationValidator(classDeserializationValidator);
        SerializationContext.setSerializationContext(serializationContext);
        //trace = new AmfTrace();
    }

    protected void tearDown() throws Exception
    {
        super.tearDown();
        SerializationContext.setSerializationContext(null);
        trace = null;
    }

    public void testSerialization()
    {
        try
        {
            URL url = this.getClass().getResource(resourceBase + "AmfxSerializationTest.class");
            File file = new File(url.getFile());
            File dir = new File(file.getParent());

            baseFilePath = dir.getAbsolutePath();

            if (dir.isDirectory())
            {
                String resourcePath = getResourcePath(baseFilePath);
                processDirectory(dir, resourcePath);
            }
        }
        catch (IOException ioe)
        {
            fail("AMFX deserialization test failed: " + ioe.getMessage());
        }
        finally
        {
            if (trace != null)
                System.out.println(trace.toString());
        }
    }

    private void processDirectory(File dir, String resourcePath) throws IOException
    {
        File[] files = dir.listFiles(new XMLFilenameFilter());

        for (int i = 0; i < files.length; i++)
        {
            File f = files[i];
            if (f.isDirectory())
            {
                resourcePath = getResourcePath(f.getAbsolutePath());
                processDirectory(f, resourcePath);
            }
            else
            {
                String testName = getTestName(f.getName());
                System.out.println("Running test: " + testName);

                FileInputStream fis = new FileInputStream(f);

                processRequest(resourcePath, testName, fis);
            }
        }
    }

    private String getResourcePath(String path)
    {
        if (path.startsWith(baseFilePath))
        {
            path = path.substring(baseFilePath.length());
            path = path.replace('\\', '/');
            return path;
        }

        return null;
    }

    private String getTestName(String fileName)
    {
        fileName = fileName.toLowerCase();
        int pos = fileName.indexOf(".xml");
        return fileName.substring(0, pos);
    }

    private void processRequest(String resourcePath, String testName, InputStream is) throws IOException
    {
        try
        {
            SerializationContext.setSerializationContext((SerializationContext)serializationContext.clone());
            // STEP 1. Deserialize Message
            ActionContext context = new ActionContext();
            context.setResponseMessage(new ActionMessage());

            ActionMessage requestMessage = new ActionMessage();
            context.setRequestMessage(requestMessage);
            AmfxMessageDeserializer deserializer = new AmfxMessageDeserializer();
            deserializer.initialize(serializationContext, is, trace);

            if (trace != null)
                trace.startRequest("Deserializing AMF/HTTP request");

            DeserializationConfirmation confirm = getConfirmation(resourcePath, testName);
            confirm.setContext(serializationContext);
            try
            {
                deserializer.readMessage(requestMessage, context);
            }
            catch (MessageException me) // For negative tests that cause MessageExceptions.
            {
                if (!confirm.isNegativeTest())
                    fail("Only negative tests might cause MessageExceptions: " + testName);
            }

            if (!confirm.isNegativeTest() && !confirm.successMatches(requestMessage))
                fail("ActionMessage did not match test: " + testName);

            // STEP 2. Re-serialize Message (Negative tests won't make it this far...)

            // create the response body
            if (requestMessage.getBodyCount() > 0 || requestMessage.getHeaderCount() > 0)
            {
                ActionMessage responseMessage = context.getResponseMessage();

                if (requestMessage.getBodyCount() > 0)
                {
                    ArrayList bodies = requestMessage.getBodies();
                    Iterator it = bodies.iterator();
                    while (it.hasNext())
                    {
                        MessageBody requestBody = (MessageBody)it.next();
                        MessageBody responseBody = new MessageBody();
                        responseBody.setData(requestBody.getData());
                        responseMessage.addBody(responseBody);
                    }
                }

                if (requestMessage.getHeaderCount() > 0)
                {
                    ArrayList headers = requestMessage.getHeaders();
                    Iterator it = headers.iterator();
                    while (it.hasNext())
                    {
                        responseMessage.addHeader((MessageHeader)it.next());
                    }
                }

                if (trace != null)
                    trace.startRequest("Serializing AMF/HTTP request");

                ByteArrayOutputStream bout = new ByteArrayOutputStream();

                AmfxMessageSerializer serializer = new AmfxMessageSerializer();
                serializer.initialize(serializationContext, bout, trace);
                serializer.writeMessage(responseMessage);

                // STEP 3. Deserialize Message once more...
                requestMessage = new ActionMessage();
                context.setRequestMessage(requestMessage);

                ByteArrayInputStream bis = new ByteArrayInputStream(bout.toByteArray());

                deserializer = new AmfxMessageDeserializer();
                deserializer.initialize(serializationContext, bis, trace);

                if (trace != null)
                    trace.startRequest("Deserializing AMF/HTTP request");

                deserializer.readMessage(requestMessage, context);

                confirm.setContext(serializationContext);

                if (!confirm.successMatches(requestMessage))
                        fail("ActionMessage did not match test on deserialization after re-serialization: " + testName);
            }
        }
        catch (MessageException ex)
        {
            throw ex;
        }
        finally
        {
            SerializationContext.setSerializationContext(null);
        }

    }

    private DeserializationConfirmation getConfirmation(String resourcePath, String testName) throws IOException
    {
        try
        {
            if (resourceBase.endsWith("/") && resourcePath.startsWith("/"))
                resourcePath = resourcePath.substring(1);

            String resource = resourceBase + resourcePath;
            if (resource.startsWith("/"))
                resource = resource.substring(1);

            String packageName = resource.replace('/', '.');

            if (packageName.length() > 0 && !packageName.endsWith("."))
                packageName = packageName + ".";

            String className = packageName + "Confirm" + testName;
            Class c = Class.forName(className);

            Object obj = c.newInstance();
            DeserializationConfirmation confirm = (DeserializationConfirmation)obj;
            return confirm;
        }
        catch (Exception e)
        {
            throw new IOException("Unable to load confirmation for testName: " + testName + " in " + resourcePath);
        }
    }

    static class XMLFilenameFilter implements FilenameFilter
    {
        public boolean accept(File dir, String name)
        {
            String child = dir.getAbsolutePath() + File.separator + name;

            File f = new File(child);

            if (f.isDirectory() && !name.startsWith(".svn"))
                return true;
            else if (name.toLowerCase().endsWith(".xml"))
                return true;
            else
                return false;
        }
    }

}
