/*
 * JBoss, the OpenSource J2EE webOS
 * 
 * Distributable under LGPL license.
 * See terms of license at gnu.org.
 */

package org.jboss.test.media.format;

import java.io.File;
import java.io.InputStream;
import java.util.Iterator;
import java.util.Map;

import javax.emb.FormatAlreadyBoundException;
import javax.emb.FormatNotFoundException;
import javax.emb.GenericMediaFormat;
import javax.emb.Media;
import javax.emb.MediaBean;
import javax.emb.MediaFormat;
import javax.emb.MediaFormatRegistry;
import javax.emb.MediaHeader;

import junit.framework.TestCase;

import org.jboss.logging.Logger;
import org.jboss.media.format.audio.mpeg.MpegAudioFormat;
import org.jboss.media.format.audio.oggvorbis.OggVorbisFormat;
import org.jboss.media.format.image.iio.IIOMediaFormatFactory;
import org.jboss.media.util.ResourceUtils;

/**
 * JBoss Media TestCase.
 * 
 * @version <tt>$Revision: 1.1 $</tt>
 * @author <a href="mailto:ricardoarguello@users.sourceforge.net">Ricardo Argüello</a>
 */
public class MediaFormatUnitTestCase extends TestCase
{
   private static final String DATA_DIR = "media/format/data/";
   private static final String IMAGE_NAME = "image.png";
   private static final String IMAGE_RESOURCE_NAME = DATA_DIR + IMAGE_NAME;
   private static final String IMAGE_MIME_TYPE = "image/png";

   private static final Logger log =
      Logger.getLogger(MediaFormatUnitTestCase.class);

   private File mediaFile;
   private InputStream contentStream;
   private Media media1, media2;
   private byte[] imageData;

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

   protected void setUp() throws Exception
   {
      initializeMappings();

      mediaFile =
         ResourceUtils.createFileFromResource(
            IMAGE_RESOURCE_NAME,
            "temp",
            IMAGE_NAME);
      contentStream =
         ResourceUtils.createStreamFromResource(IMAGE_RESOURCE_NAME);
      media1 = new MediaBean(mediaFile, IMAGE_MIME_TYPE);
      media2 =
         new MediaBean(contentStream, IMAGE_MIME_TYPE, mediaFile.getName());
      imageData = ResourceUtils.loadBinaryData(IMAGE_RESOURCE_NAME);
   }

   protected void tearDown() throws Exception
   {
      deinitializeMappings();

      mediaFile = null;
      contentStream = null;
      media1 = null;
      media2 = null;
      imageData = null;
   }

   public void testMediaBeanProperties() throws Exception
   {
      assertEquals(media1.getName(), media2.getName());
      assertEquals(media1.getMimeType(), media2.getMimeType());
      assertEquals(media1.getSize(), media2.getSize());
      assertEquals(media1.getContent(), media2.getContent());
   }

   /**
    * Test Media.readContent(long, byte[]) when the position is the same size
    * of the media content size.
    */
   public void testMediaContent() throws Exception
   {
      byte[] buffer = new byte[(int) media1.getSize()];
      int i = media1.readContent(media1.getSize(), buffer);
      assertEquals(buffer, new byte[(int) media1.getSize()]);
   }

   public void testMediaFormatRegistry() throws Exception
   {
      MediaFormatRegistry registry = MediaFormatRegistry.SINGLETON;
      Iterator it = registry.getFileExtensions();

      if (it == null)
      {
         fail();
      }

      while (it.hasNext())
      {
         String fileExtension = (String) it.next();
         //log.info("fileExtension: " + fileExtension);
      }

      try
      {
         registry.bind("foo", new GenericMediaFormat());
      }
      catch (FormatAlreadyBoundException e)
      {
         fail();
      }

      try
      {
         registry.bind("foo", new GenericMediaFormat());
         fail();
      }
      catch (FormatAlreadyBoundException e)
      {
      }

      MediaFormatRegistry registry2 = MediaFormatRegistry.SINGLETON;

      try
      {
         MediaFormat foo = registry2.lookup("foo");
      }
      catch (FormatNotFoundException e)
      {
         fail();
      }

      registry.rebind("foo", new GenericMediaFormat());

      try
      {
         registry.unbind("foo");
      }
      catch (FormatNotFoundException e)
      {
         fail();
      }

      try
      {
         MediaFormat foo = registry2.lookup("foo");
         fail();
      }
      catch (FormatNotFoundException e)
      {
      }
   }

   public void testHeaderExtraction() throws Exception
   {
      MediaHeader mediaHeader = media1.getHeader();

      String[] fields = mediaHeader.getFieldNames();
      for (int i = 0; i < fields.length; i++)
         log.info(fields[i] + "=" + mediaHeader.getField(fields[i]));

      assertEquals(new Integer(263), mediaHeader.getField("width"));
      assertEquals(new Integer(54), mediaHeader.getField("height"));
      assertEquals("8", mediaHeader.getField("bitDepth"));
      assertEquals("RGB", mediaHeader.getField("colorType"));
      assertEquals("deflate", mediaHeader.getField("compressionMethod"));
      assertEquals("adaptive", mediaHeader.getField("filterMethod"));
      assertEquals("none", mediaHeader.getField("interlaceMethod"));
   }

   private void assertEquals(byte[] expected, byte[] actual)
   {
      assertEquals(expected.length, actual.length);
      for (int i = 0; i < expected.length; ++i)
         assertEquals(expected[i], actual[i]);
   }

   public static void initializeMappings() throws Exception
   {
      // Image I/O support:
      Map mediaFormats = IIOMediaFormatFactory.createMediaFormats();

      // MPEG support:
      mediaFormats.put("mp3", new MpegAudioFormat());

      // Ogg Vorbis support:
      mediaFormats.put("ogg", new OggVorbisFormat());

      MediaFormatRegistry mediaFormatRegistry = MediaFormatRegistry.SINGLETON;

      Iterator it = mediaFormats.keySet().iterator();

      while (it.hasNext())
      {
         String extension = (String) it.next();
         MediaFormat mediaFormat = (MediaFormat) mediaFormats.get(extension);
         mediaFormatRegistry.bind(extension, mediaFormat);
      }
   }

   public static void deinitializeMappings() throws Exception
   {
      // Image I/O support:
      Map mediaFormats = IIOMediaFormatFactory.createMediaFormats();

      // MPEG support:
      mediaFormats.put("mp3", new MpegAudioFormat());

      // Ogg Vorbis support:
      mediaFormats.put("ogg", new OggVorbisFormat());

      MediaFormatRegistry mediaFormatRegistry = MediaFormatRegistry.SINGLETON;

      Iterator it = mediaFormats.keySet().iterator();

      while (it.hasNext())
      {
         String extension = (String) it.next();
         mediaFormatRegistry.unbind(extension);
      }
   }
}