package org.forkalsrud.album.video;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;

import org.forkalsrud.album.exif.Dimension;
import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.hamcrest.core.IsInstanceOf.instanceOf;

public class FlvMetadataTest {

    private ByteArrayOutputStream out = new ByteArrayOutputStream();
    private ByteArrayInputStream in;
    FlvMetadata md0 = new FlvMetadata();

    private void flip() {
        in = new ByteArrayInputStream(out.toByteArray());
        out.reset();
    }

    @Test
    public void testMerge() throws Exception {

        FlvMetadata md1 = new FlvMetadata();
        md1.setDuration("3.14");
        md1.setDimension(new Dimension(5, 6));

        FlvMetadata md2 = new FlvMetadata();
        md2.merge(md1);
        assertEquals(3.14d, md2.get("duration"));
        assertEquals(5d, md2.get("width"));
        assertEquals(6d, md2.get("height"));
    }

    @Test
    public void testReadWriteDouble() throws Exception {
        double value = 3.14;
        md0.writeDouble(out, value);
        flip();
        assertThat(md0.readDouble(in), equalTo(value));
    }

    @Test
    public void testReadWriteInt() throws Exception {
        int value = 45;
        // uint16
        md0.writeUint16(out, value);
        flip();
        assertEquals(value, md0.readUint16(in));

        // uint24
        md0.writeUint24(out, value);
        flip();
        assertEquals(value, md0.readUint24(in));

        // uint32
        md0.writeUint32(out, value);
        flip();
        assertEquals(value, md0.readUint32(in));

        // timestamp
        md0.writeTimestamp(out, value);
        flip();
        assertEquals(value, md0.readTimestamp(in));
    }

    @Test
    public void testReadWriteString() throws Exception {
        String value = "awsome";
        md0.writeFlvString(out, value);
        flip();
        assertEquals(value, md0.readString(in));
    }

    @Test
    public void testWriteReadMetadata() throws Exception {

        FlvMetadata md1 = new FlvMetadata();
        md1.setDuration("3.14");
        md1.setDimension(new Dimension(5, 6));

        md1.writeScriptDataObject(out);
        flip();

        FlvMetadata md2 = new FlvMetadata();
        md2.read(in);

        assertEquals("3.14", md2.get("duration").toString());
        assertEquals(5, md2.getWidth());
        assertEquals(6, md2.getHeight());
    }


    @Test
    public void testReadWriteMetadata() throws Exception {

        InputStream is = getClass().getResourceAsStream("/VideoAd.flv");
        is.read(new byte[24]); // offset to start of scriptdata

        FlvMetadata md1 = new FlvMetadata();
        md1.read(is);

        md1.writeScriptDataObject(out);
        flip();

        FlvMetadata md2 = new FlvMetadata();
        md2.read(in);

        assertEquals(md1, md2);
    }

    @Test
    public void testSetDuration() {
    	FlvMetadata m = new FlvMetadata();
    	m.setDuration("1:02:03");
    	Object o = m.get("duration");
    	assertThat(o, instanceOf(Double.class));
    	Double durationSeconds = (Double) o;
    	assertThat(durationSeconds.intValue(), equalTo(3600 + 2*60 + 3));
    }
}
