/* ====================================================================
   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 org.apache.poi.hslf.usermodel;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.awt.Dimension;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.List;

import org.apache.poi.POIDataSamples;
import org.apache.poi.hslf.blip.DIB;
import org.apache.poi.hslf.blip.EMF;
import org.apache.poi.hslf.blip.JPEG;
import org.apache.poi.hslf.blip.PICT;
import org.apache.poi.hslf.blip.PNG;
import org.apache.poi.hslf.blip.WMF;
import org.apache.poi.sl.image.ImageHeaderEMF;
import org.apache.poi.sl.image.ImageHeaderPICT;
import org.apache.poi.sl.image.ImageHeaderWMF;
import org.apache.poi.sl.usermodel.PictureData.PictureType;
import org.apache.poi.util.Units;
import org.junit.Ignore;
import org.junit.Test;

/**
 * Test adding/reading pictures
 *
 * @author Yegor Kozlov
 */
public final class TestPictures {
    private static POIDataSamples slTests = POIDataSamples.getSlideShowInstance();

    /**
     * Test read/write Macintosh PICT
     */
    @Test
    public void testPICT() throws IOException {
        HSLFSlideShow ppt = new HSLFSlideShow();

        HSLFSlide slide = ppt.createSlide();
        byte[] src_bytes = slTests.readFile("cow.pict");
        HSLFPictureData data = ppt.addPicture(src_bytes, PictureType.PICT);
        ImageHeaderPICT nHeader = new ImageHeaderPICT(src_bytes, 512);
        final int expWidth = 197, expHeight = 137;
        Dimension nDim = nHeader.getSize();
        assertEquals(expWidth, nDim.getWidth(), 0);
        assertEquals(expHeight, nDim.getHeight(), 0);
        
        Dimension dim = data.getImageDimensionInPixels();
        assertEquals(Units.pointsToPixel(expWidth), dim.getWidth(), 0);
        assertEquals(Units.pointsToPixel(expHeight), dim.getHeight(), 0);
        
        HSLFPictureShape pict = new HSLFPictureShape(data);
        assertEquals(data.getIndex(), pict.getPictureIndex());
        slide.addShape(pict);

        //serialize and read again
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ppt.write(out);
        out.close();

        ppt = new HSLFSlideShow(new HSLFSlideShowImpl(new ByteArrayInputStream(out.toByteArray())));

        //make sure we can read this picture shape and it refers to the correct picture data
        List<HSLFShape> sh = ppt.getSlides().get(0).getShapes();
        assertEquals(1, sh.size());
        pict = (HSLFPictureShape)sh.get(0);
        assertEquals(data.getIndex(), pict.getPictureIndex());

        //check picture data
        List<HSLFPictureData> pictures = ppt.getPictureData();
        assertEquals(1, pictures.size());
        
        HSLFPictureData pd = pictures.get(0);
        dim = pd.getImageDimension();
        assertEquals(expWidth, dim.width);
        assertEquals(expHeight, dim.height);
        
        //the Picture shape refers to the PictureData object in the Presentation
        assertEquals(pict.getPictureData(), pd);

        assertEquals(1, pictures.size());
        assertEquals(PictureType.PICT, pd.getType());
        assertTrue(pd instanceof PICT);
        //compare the content of the initial file with what is stored in the PictureData
        byte[] ppt_bytes = pd.getData();
        assertEquals(src_bytes.length, ppt_bytes.length);
        //in PICT the first 512 bytes are MAC specific and may not be preserved, ignore them
        byte[] b1 = new byte[src_bytes.length-512];
        System.arraycopy(src_bytes, 512, b1, 0, b1.length);
        byte[] b2 = new byte[ppt_bytes.length-512];
        System.arraycopy(ppt_bytes, 512, b2, 0, b2.length);
        assertArrayEquals(b1, b2);
    }

    /**
     * Test read/write WMF
     */
    @Test
    public void testWMF() throws IOException {
        HSLFSlideShow ppt = new HSLFSlideShow();

        HSLFSlide slide = ppt.createSlide();
        byte[] src_bytes = slTests.readFile("santa.wmf");
        HSLFPictureData data = ppt.addPicture(src_bytes, PictureType.WMF);
        ImageHeaderWMF nHeader = new ImageHeaderWMF(src_bytes, 0);
        final int expWidth = 136, expHeight = 146;
        Dimension nDim = nHeader.getSize();
        assertEquals(expWidth, nDim.getWidth(), 0);
        assertEquals(expHeight, nDim.getHeight(), 0);

        Dimension dim = data.getImageDimensionInPixels();
        assertEquals(Units.pointsToPixel(expWidth), dim.getWidth(), 0);
        assertEquals(Units.pointsToPixel(expHeight), dim.getHeight(), 0);
        
        HSLFPictureShape pict = new HSLFPictureShape(data);
        assertEquals(data.getIndex(), pict.getPictureIndex());
        slide.addShape(pict);

        //serialize and read again
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ppt.write(out);
        out.close();

        ppt = new HSLFSlideShow(new HSLFSlideShowImpl(new ByteArrayInputStream(out.toByteArray())));

        //make sure we can read this picture shape and it refers to the correct picture data
        List<HSLFShape> sh = ppt.getSlides().get(0).getShapes();
        assertEquals(1, sh.size());
        pict = (HSLFPictureShape)sh.get(0);
        assertEquals(data.getIndex(), pict.getPictureIndex());

        //check picture data
        List<HSLFPictureData> pictures = ppt.getPictureData();
        assertEquals(1, pictures.size());

        HSLFPictureData pd = pictures.get(0);
        dim = pd.getImageDimension();
        assertEquals(expWidth, dim.width);
        assertEquals(expHeight, dim.height);
        
        //the Picture shape refers to the PictureData object in the Presentation
        assertEquals(pict.getPictureData(), pd);
        
        assertEquals(PictureType.WMF, pd.getType());
        assertTrue(pd instanceof WMF);
        //compare the content of the initial file with what is stored in the PictureData
        byte[] ppt_bytes = pd.getData();
        assertEquals(src_bytes.length, ppt_bytes.length);
        //in WMF the first 22 bytes - is a metafile header
        byte[] b1 = new byte[src_bytes.length-22];
        System.arraycopy(src_bytes, 22, b1, 0, b1.length);
        byte[] b2 = new byte[ppt_bytes.length-22];
        System.arraycopy(ppt_bytes, 22, b2, 0, b2.length);
        assertArrayEquals(b1, b2);
    }

    /**
     * Test read/write EMF
     */
    @Test
    public void testEMF() throws IOException {
        HSLFSlideShow ppt = new HSLFSlideShow();

        HSLFSlide slide = ppt.createSlide();
        byte[] src_bytes = slTests.readFile("wrench.emf");
        HSLFPictureData data = ppt.addPicture(src_bytes, PictureType.EMF);
        ImageHeaderEMF nHeader = new ImageHeaderEMF(src_bytes, 0);
        final int expWidth = 190, expHeight = 115;
        Dimension nDim = nHeader.getSize();
        assertEquals(expWidth, nDim.getWidth(), 0);
        assertEquals(expHeight, nDim.getHeight(), 0);

        Dimension dim = data.getImageDimensionInPixels();
        assertEquals(Units.pointsToPixel(expWidth), dim.getWidth(), 0);
        assertEquals(Units.pointsToPixel(expHeight), dim.getHeight(), 0);
        
        HSLFPictureShape pict = new HSLFPictureShape(data);
        assertEquals(data.getIndex(), pict.getPictureIndex());
        slide.addShape(pict);

        //serialize and read again
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ppt.write(out);
        out.close();

        ppt = new HSLFSlideShow(new HSLFSlideShowImpl(new ByteArrayInputStream(out.toByteArray())));

        //make sure we can get this picture shape and it refers to the correct picture data
        List<HSLFShape> sh = ppt.getSlides().get(0).getShapes();
        assertEquals(1, sh.size());
        pict = (HSLFPictureShape)sh.get(0);
        assertEquals(data.getIndex(), pict.getPictureIndex());

        //check picture data
        List<HSLFPictureData> pictures = ppt.getPictureData();
        assertEquals(1, pictures.size());
        
        HSLFPictureData pd = pictures.get(0);
        dim = pd.getImageDimension();
        assertEquals(expWidth, dim.width);
        assertEquals(expHeight, dim.height);
        
        //the Picture shape refers to the PictureData object in the Presentation
        assertEquals(pict.getPictureData(), pd);

        assertEquals(1, pictures.size());
        assertEquals(PictureType.EMF, pd.getType());
        assertTrue(pd instanceof EMF);
        //compare the content of the initial file with what is stored in the PictureData
        byte[] ppt_bytes = pd.getData();
        assertArrayEquals(src_bytes, ppt_bytes);
    }

    /**
     * Test read/write PNG
     */
    @Test
    public void testPNG() throws IOException {
        HSLFSlideShow ppt = new HSLFSlideShow();

        HSLFSlide slide = ppt.createSlide();
        byte[] src_bytes = slTests.readFile("tomcat.png");
        HSLFPictureData data = ppt.addPicture(src_bytes, PictureType.PNG);
        HSLFPictureShape pict = new HSLFPictureShape(data);
        assertEquals(data.getIndex(), pict.getPictureIndex());
        slide.addShape(pict);

        //serialize and read again
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ppt.write(out);
        out.close();

        ppt = new HSLFSlideShow(new HSLFSlideShowImpl(new ByteArrayInputStream(out.toByteArray())));

        //make sure we can read this picture shape and it refers to the correct picture data
        List<HSLFShape> sh = ppt.getSlides().get(0).getShapes();
        assertEquals(1, sh.size());
        pict = (HSLFPictureShape)sh.get(0);
        assertEquals(data.getIndex(), pict.getPictureIndex());

        //check picture data
        List<HSLFPictureData> pictures = ppt.getPictureData();
        //the Picture shape refers to the PictureData object in the Presentation
        assertEquals(pict.getPictureData(), pictures.get(0));

        assertEquals(1, pictures.size());
        assertEquals(PictureType.PNG, pictures.get(0).getType());
        assertTrue(pictures.get(0) instanceof PNG);
        //compare the content of the initial file with what is stored in the PictureData
        byte[] ppt_bytes = pictures.get(0).getData();
        assertArrayEquals(src_bytes, ppt_bytes);
    }

    /**
     * Test read/write JPEG
     */
    @Test
    public void testJPEG() throws IOException {
        HSLFSlideShow ppt = new HSLFSlideShow();

        HSLFSlide slide = ppt.createSlide();
        byte[] src_bytes = slTests.readFile("clock.jpg");
        HSLFPictureData data = ppt.addPicture(src_bytes, PictureType.JPEG);

        HSLFPictureShape pict = new HSLFPictureShape(data);
        assertEquals(data.getIndex(), pict.getPictureIndex());
        slide.addShape(pict);

        //serialize and read again
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ppt.write(out);
        out.close();

        ppt = new HSLFSlideShow(new HSLFSlideShowImpl(new ByteArrayInputStream(out.toByteArray())));

        //make sure we can read this picture shape and it refers to the correct picture data
        List<HSLFShape> sh = ppt.getSlides().get(0).getShapes();
        assertEquals(1, sh.size());
        pict = (HSLFPictureShape)sh.get(0);
        assertEquals(data.getIndex(), pict.getPictureIndex());

        //check picture data
        List<HSLFPictureData> pictures = ppt.getPictureData();
        //the Picture shape refers to the PictureData object in the Presentation
        assertEquals(pict.getPictureData(), pictures.get(0));

        assertEquals(1, pictures.size());
        assertEquals(PictureType.JPEG, pictures.get(0).getType());
        assertTrue(pictures.get(0) instanceof JPEG);
        //compare the content of the initial file with what is stored in the PictureData
        byte[] ppt_bytes = pictures.get(0).getData();
        assertArrayEquals(src_bytes, ppt_bytes);
    }

    /**
     * Test read/write DIB
     */
    @Test
    public void testDIB() throws IOException {
        HSLFSlideShow ppt = new HSLFSlideShow();

        HSLFSlide slide = ppt.createSlide();
        byte[] src_bytes = slTests.readFile("clock.dib");
        HSLFPictureData data = ppt.addPicture(src_bytes, PictureType.DIB);
        HSLFPictureShape pict = new HSLFPictureShape(data);
        assertEquals(data.getIndex(), pict.getPictureIndex());
        slide.addShape(pict);

        //serialize and read again
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ppt.write(out);
        out.close();

        ppt = new HSLFSlideShow(new HSLFSlideShowImpl(new ByteArrayInputStream(out.toByteArray())));

        //make sure we can read this picture shape and it refers to the correct picture data
        List<HSLFShape> sh = ppt.getSlides().get(0).getShapes();
        assertEquals(1, sh.size());
        pict = (HSLFPictureShape)sh.get(0);
        assertEquals(data.getIndex(), pict.getPictureIndex());

        //check picture data
        List<HSLFPictureData> pictures = ppt.getPictureData();
        //the Picture shape refers to the PictureData object in the Presentation
        assertEquals(pict.getPictureData(), pictures.get(0));

        assertEquals(1, pictures.size());
        assertEquals(PictureType.DIB, pictures.get(0).getType());
        assertTrue(pictures.get(0) instanceof DIB);
        //compare the content of the initial file with what is stored in the PictureData
        byte[] ppt_bytes = pictures.get(0).getData();
        assertArrayEquals(src_bytes, ppt_bytes);
    }

    /**
     * Read pictures in different formats from a reference slide show
     */
    @Test
    public void testReadPictures() throws IOException {

        byte[] src_bytes, ppt_bytes, b1, b2;
        HSLFPictureShape pict;
        HSLFPictureData pdata;

        HSLFSlideShow ppt = new HSLFSlideShow(slTests.openResourceAsStream("pictures.ppt"));
        List<HSLFSlide> slides = ppt.getSlides();
        List<HSLFPictureData> pictures = ppt.getPictureData();
        assertEquals(5, pictures.size());

        pict = (HSLFPictureShape)slides.get(0).getShapes().get(0); //the first slide contains JPEG
        pdata = pict.getPictureData();
        assertTrue(pdata instanceof JPEG);
        assertEquals(PictureType.JPEG, pdata.getType());
        src_bytes = pdata.getData();
        ppt_bytes = slTests.readFile("clock.jpg");
        assertArrayEquals(src_bytes, ppt_bytes);

        pict = (HSLFPictureShape)slides.get(1).getShapes().get(0); //the second slide contains PNG
        pdata = pict.getPictureData();
        assertTrue(pdata instanceof PNG);
        assertEquals(PictureType.PNG, pdata.getType());
        src_bytes = pdata.getData();
        ppt_bytes = slTests.readFile("tomcat.png");
        assertArrayEquals(src_bytes, ppt_bytes);

        pict = (HSLFPictureShape)slides.get(2).getShapes().get(0); //the third slide contains WMF
        pdata = pict.getPictureData();
        assertTrue(pdata instanceof WMF);
        assertEquals(PictureType.WMF, pdata.getType());
        src_bytes = pdata.getData();
        ppt_bytes = slTests.readFile("santa.wmf");
        assertEquals(src_bytes.length, ppt_bytes.length);
        //ignore the first 22 bytes - it is a WMF metafile header
        b1 = new byte[src_bytes.length-22];
        System.arraycopy(src_bytes, 22, b1, 0, b1.length);
        b2 = new byte[ppt_bytes.length-22];
        System.arraycopy(ppt_bytes, 22, b2, 0, b2.length);
        assertArrayEquals(b1, b2);

        pict = (HSLFPictureShape)slides.get(3).getShapes().get(0); //the forth slide contains PICT
        pdata = pict.getPictureData();
        assertTrue(pdata instanceof PICT);
        assertEquals(PictureType.PICT, pdata.getType());
        src_bytes = pdata.getData();
        ppt_bytes = slTests.readFile("cow.pict");
        assertEquals(src_bytes.length, ppt_bytes.length);
        //ignore the first 512 bytes - it is a MAC specific crap
        b1 = new byte[src_bytes.length-512];
        System.arraycopy(src_bytes, 512, b1, 0, b1.length);
        b2 = new byte[ppt_bytes.length-512];
        System.arraycopy(ppt_bytes, 512, b2, 0, b2.length);
        assertArrayEquals(b1, b2);

        pict = (HSLFPictureShape)slides.get(4).getShapes().get(0); //the fifth slide contains EMF
        pdata = pict.getPictureData();
        assertTrue(pdata instanceof EMF);
        assertEquals(PictureType.EMF, pdata.getType());
        src_bytes = pdata.getData();
        ppt_bytes = slTests.readFile("wrench.emf");
        assertArrayEquals(src_bytes, ppt_bytes);

        ppt.close();
    }

	/**
	 * Test that on a party corrupt powerpoint document, which has
	 *  crazy pictures of type 0, we do our best.
	 */
    @Test
	public void testZeroPictureType() throws IOException {
		HSLFSlideShowImpl hslf = new HSLFSlideShowImpl(slTests.openResourceAsStream("PictureTypeZero.ppt"));

		// Should still have 2 real pictures
		assertEquals(2, hslf.getPictureData().size());
		// Both are real pictures, both WMF
		assertEquals(PictureType.WMF, hslf.getPictureData().get(0).getType());
		assertEquals(PictureType.WMF, hslf.getPictureData().get(1).getType());

		// Now test what happens when we use the SlideShow interface
		HSLFSlideShow ppt = new HSLFSlideShow(hslf);
        List<HSLFSlide> slides = ppt.getSlides();
        List<HSLFPictureData> pictures = ppt.getPictureData();
        assertEquals(12, slides.size());
        assertEquals(2, pictures.size());

		HSLFPictureShape pict;
		HSLFPictureData pdata;

        pict = (HSLFPictureShape)slides.get(0).getShapes().get(1); // 2nd object on 1st slide
        pdata = pict.getPictureData();
        assertTrue(pdata instanceof WMF);
        assertEquals(PictureType.WMF, pdata.getType());

        pict = (HSLFPictureShape)slides.get(0).getShapes().get(2); // 3rd object on 1st slide
        pdata = pict.getPictureData();
        assertTrue(pdata instanceof WMF);
        assertEquals(PictureType.WMF, pdata.getType());
        
        ppt.close();
	}

    /**
     * YK: The test is disabled because the owner asked to delete the test file from POI svn.
     * See "Please remove my file from your svn" on @poi-dev from Dec 12, 2013
     */
    @Test
    @Ignore
	public void testZeroPictureLength() throws IOException {
        // take the data from www instead of test directory
        URL url = new URL("http://www.cs.sfu.ca/~anoop/courses/CMPT-882-Fall-2002/chris.ppt");
		HSLFSlideShowImpl hslf = new HSLFSlideShowImpl(url.openStream());

		// Should still have 2 real pictures
		assertEquals(2, hslf.getPictureData().size());
		// Both are real pictures, both WMF
		assertEquals(PictureType.WMF, hslf.getPictureData().get(0).getType());
		assertEquals(PictureType.WMF, hslf.getPictureData().get(1).getType());

		// Now test what happens when we use the SlideShow interface
		HSLFSlideShow ppt = new HSLFSlideShow(hslf);
        List<HSLFSlide> slides = ppt.getSlides();
        List<HSLFPictureData> pictures = ppt.getPictureData();
        assertEquals(27, slides.size());
        assertEquals(2, pictures.size());

		HSLFPictureShape pict;
		HSLFPictureData pdata;

        pict = (HSLFPictureShape)slides.get(6).getShapes().get(13);
        pdata = pict.getPictureData();
        assertTrue(pdata instanceof WMF);
        assertEquals(PictureType.WMF, pdata.getType());

        pict = (HSLFPictureShape)slides.get(7).getShapes().get(13);
        pdata = pict.getPictureData();
        assertTrue(pdata instanceof WMF);
        assertEquals(PictureType.WMF, pdata.getType());

        //add a new picture, it should be correctly appended to the Pictures stream
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        for(HSLFPictureData p : pictures) p.write(out);
        out.close();

        int streamSize = out.size();

        HSLFPictureData data = HSLFPictureData.create(PictureType.JPEG);
        data.setData(new byte[100]);
        int offset = hslf.addPicture(data);
        assertEquals(streamSize, offset);
        assertEquals(3, ppt.getPictureData().size());

        ppt.close();
    }

    @Test
    public void testGetPictureName() throws IOException {
        HSLFSlideShow ppt = new HSLFSlideShow(slTests.openResourceAsStream("ppt_with_png.ppt"));
        HSLFSlide slide = ppt.getSlides().get(0);

        HSLFPictureShape p = (HSLFPictureShape)slide.getShapes().get(0); //the first slide contains JPEG
        assertEquals("test", p.getPictureName());
        ppt.close();
    }

    @Test
    public void testSetPictureName() throws IOException {
        HSLFSlideShow ppt = new HSLFSlideShow();

        HSLFSlide slide = ppt.createSlide();
        byte[] img = slTests.readFile("tomcat.png");
        HSLFPictureData data = ppt.addPicture(img, PictureType.PNG);
        HSLFPictureShape pict = new HSLFPictureShape(data);
        pict.setPictureName("tomcat.png");
        slide.addShape(pict);

        //serialize and read again
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ppt.write(out);
        out.close();

        ppt = new HSLFSlideShow(new ByteArrayInputStream(out.toByteArray()));

        HSLFPictureShape p = (HSLFPictureShape)ppt.getSlides().get(0).getShapes().get(0);
        assertEquals("tomcat.png", p.getPictureName());
    }
}
