package com.ibm.emb.test;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.StringTokenizer;

import javax.emb.MediaException;
import javax.emb.MediaFormat;
import javax.emb.MediaFormatRegistry;
import javax.emb.MediaHeader;

import junit.framework.Test;
import junit.framework.TestSuite;

import com.ibm.emb.junit.EMBStaticHelper;
import com.ibm.emb.junit.EMBTestCaseBase;

/**
 * <pre>
 * 
 *  
 *   
 *    Line Item: MFB API 
 *    Subcategory 1: javax.emb
 *    Subcategory 2: MediaHeader
 *    
 *   
 *  
 * </pre>
 */
public abstract class MediaHeaderTest extends EMBTestCaseBase {

    public MediaHeaderTest(String name) throws MediaException {
        super(name);
    }

    /**
     * stdSuite method of this test class instantiates all tests necesssary to
     * for the standard compliance tests
     * @param String complete class Name of the implementor of the abstract test
     */
    public static Test stdSuite(String TestCaseImplementor) {
        TestSuite suite = new TestSuite(TestCaseImplementor);
        try {
            Class implementorClass = Class.forName(TestCaseImplementor);
            java.lang.reflect.Constructor implementorConstructor = implementorClass
                    .getDeclaredConstructor(new Class[] {String.class});
            suite.addTest((Test) implementorConstructor.newInstance(new String[] {"testEMB037"}));
            suite.addTest((Test) implementorConstructor.newInstance(new String[] {"testEMB038"}));
        } catch (java.lang.reflect.InvocationTargetException ex) {
            String msg = "error dynamically creating " + TestCaseImplementor + " " + ex.toString();
            EMBStaticHelper.testTrace(msg);
            throw new RuntimeException(msg);
        } catch (ClassNotFoundException ex) {
            String msg = "Class not found " + TestCaseImplementor + " " + ex.toString();
            EMBStaticHelper.testTrace(msg);
            throw new RuntimeException(msg);
        } catch (NoSuchMethodException ex) {
            String msg = "No such method in " + TestCaseImplementor + " " + ex.toString();
            EMBStaticHelper.testTrace(msg);
            throw new RuntimeException(msg);
        } catch (InstantiationException ex) {
            String msg = TestCaseImplementor + " " + ex.toString();
            EMBStaticHelper.testTrace(msg);
            throw new RuntimeException(msg);
        } catch (IllegalAccessException ex) {
            String msg = TestCaseImplementor + " " + ex.toString();
            EMBStaticHelper.testTrace(msg);
            throw new RuntimeException(msg);
        }
        return suite;
    }

    /**
     * abstract method to create an instance of mediaHeader with no parameters
     * this method needs to be implemented in the test subclass and will create
     * an instance of the concrete implementation of the class under test
     */
    public abstract MediaHeader createMediaHeader() throws MediaException, IOException;

    /**
     * <pre>
     * 
     *  
     *   
     *    Testcase Name: getField(String fieldName)
     *    Testcase Number: EMB037
     *    
     *    setup: access file containing a list of all implemented Media formats and sample files
     *    
     *    test procedure:
     *    1.for each format, call extractHeader().getField(null)
     *      expected result: NullPointerException
     *    
     *    2.for each format, call extractHeader().getField(&quot;%$&amp;//&amp;%?%&amp;&quot;)
     *      expected result: null
     *    
     *    3.for each format, call extractHeader().getFieldNames()
     *      for each field, call getField()
     *      expected result: not null
     *    
     *   
     *  
     * </pre>
     */
    public void testEMB037() throws MediaException, IOException {

        // retrieve Media formats
        String allMediaFormats = embTestConfig.getAllMediaFormats();
        allMediaFormats = allMediaFormats.trim();

        // token individual Media formats
        StringTokenizer mediaTokenizer = new StringTokenizer(allMediaFormats, ";");
        String formatInfo = null;
        StringTokenizer formatInfoTokenizer = null;

        while (mediaTokenizer.hasMoreTokens()) {
            formatInfo = mediaTokenizer.nextToken();
            formatInfoTokenizer = new StringTokenizer(formatInfo);

            assertEquals("test initialization: allMediaFormats property not properly formatted", 3, formatInfoTokenizer
                    .countTokens());

            String fullClassName = formatInfoTokenizer.nextToken();
            String fileExtension = formatInfoTokenizer.nextToken();
            String mediaFileName = formatInfoTokenizer.nextToken();

            String mediaFullPath = embTestConfig.getMediaDir() + File.separator + mediaFileName;

            try {
                File mediaFile = new File(mediaFullPath);
                InputStream mediaFileInputStream = new FileInputStream(mediaFile);
                MediaFormat mediaFormat = (MediaFormat) Class.forName(fullClassName).newInstance();
                MediaHeader testInstance = mediaFormat.extractHeader(mediaFileInputStream);
                mediaFileInputStream.close();
                MediaFormatRegistry formatRegistry = MediaFormatRegistry.SINGLETON;
                formatRegistry.rebind(fileExtension, (MediaFormat) Class.forName(fullClassName).newInstance());

                //
                // test 1
                //
                try {
                    testInstance.getField(null);
                    fail("[" + testInstance.getClass().getName() + "] test 1: " + "Should throw a NullPointerException");
                } catch (NullPointerException e) {
                    testTrace("[" + testInstance.getClass().getName() + "] test 1 passed");
                } catch (Exception e) {
                    fail("[" + testInstance.getClass().getName() + "] test 1: "
                            + "Should throw a NullPointerException but threw " + e.toString());
                }
                //
                // test 2
                //
                assertNull("[" + testInstance.getClass().getName() + "] test 2: ", testInstance.getField("%$&//&%?%&"));
                testTrace("[" + testInstance.getClass().getName() + "] test 2 passed");
                //
                // test 3
                //
                String[] fieldNames = testInstance.getFieldNames();
                for (int i = 0; i < fieldNames.length; i++) {
                    assertNotNull("[" + testInstance.getClass().getName() + "] test 3: ", testInstance
                            .getField(fieldNames[i]));
                }
                testTrace("[" + testInstance.getClass().getName() + "] test 3 passed");

            } catch (ClassNotFoundException e) {
                fail("Class not found: " + e.getMessage());
            } catch (IllegalAccessException e) {
                fail("Illegal access: " + e.getMessage());
            } catch (InstantiationException e) {
                fail("Instantiation exception; " + e.getMessage());
            }
        }
        succeed();
    }

    /**
     * <pre>
     * 
     *  
     *   
     *    Testcase Name: getFieldNames()
     *    Testcase Number: EMB038
     *    
     *    setup: access file containing a list of all implemented Media formats and sample files
     *    
     *    test procedure:
     *    1.for each format, call extractHeader.getFieldNames()
     *      expected result: not null
     *    
     *   
     *  
     * </pre>
     */
    public void testEMB038() throws MediaException, IOException {
        // retrieve Media formats
        String allMediaFormats = embTestConfig.getAllMediaFormats();
        allMediaFormats = allMediaFormats.trim();

        // token individual Media formats
        StringTokenizer mediaTokenizer = new StringTokenizer(allMediaFormats, ";");
        String formatInfo = null;
        StringTokenizer formatInfoTokenizer = null;

        while (mediaTokenizer.hasMoreTokens()) {
            formatInfo = mediaTokenizer.nextToken();
            formatInfoTokenizer = new StringTokenizer(formatInfo);

            assertEquals("test initialization: ", 3, formatInfoTokenizer.countTokens());

            String fullClassName = formatInfoTokenizer.nextToken();
            String fileExtension = formatInfoTokenizer.nextToken();
            String mediaFileName = formatInfoTokenizer.nextToken();

            String mediaFullPath = embTestConfig.getMediaDir() + File.separator + mediaFileName;

            try {
                File mediaFile = new File(mediaFullPath);
                InputStream mediaFileInputStream = new FileInputStream(mediaFile);
                MediaFormat mediaFormat = (MediaFormat) Class.forName(fullClassName).newInstance();
                MediaHeader testInstance = mediaFormat.extractHeader(mediaFileInputStream);
                mediaFileInputStream.close();
                MediaFormatRegistry formatRegistry = MediaFormatRegistry.SINGLETON;
                formatRegistry.rebind(fileExtension, (MediaFormat) Class.forName(fullClassName).newInstance());

                //
                // test 1
                //
                assertNotNull("[" + testInstance.getClass().getName() + "] test 1: ", testInstance.getFieldNames());
                testTrace("[" + testInstance.getClass().getName() + "] test 1 passed");

            } catch (ClassNotFoundException e) {
                fail("Class not found: " + e.getMessage());
            } catch (IllegalAccessException e) {
                fail("Illegal access: " + e.getMessage());
            } catch (InstantiationException e) {
                fail("Instantiation exception; " + e.getMessage());
            }
        }

        succeed();
    }

}