/*
 * 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.commons.sanselan.formats.jpeg.iptc;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.sanselan.common.bytesource.ByteSource;
import org.apache.commons.sanselan.common.bytesource.ByteSourceFile;
import org.apache.commons.sanselan.formats.jpeg.JpegImageParser;
import org.apache.commons.sanselan.formats.jpeg.JpegPhotoshopMetadata;
import org.apache.commons.sanselan.formats.jpeg.iptc.IptcRecord;
import org.apache.commons.sanselan.formats.jpeg.iptc.JpegIptcRewriter;
import org.apache.commons.sanselan.formats.jpeg.iptc.PhotoshopApp13Data;
import org.apache.commons.sanselan.util.Debug;

public class IptcUpdateTest extends IptcBaseTest
{
    private List imagesWithIptcData;

    @Override
    public void setUp() throws Exception
    {
        super.setUp();

        imagesWithIptcData = getImagesWithIptcData();
    }

    @Override
    public void tearDown() throws Exception
    {
        super.tearDown();

        imagesWithIptcData = null;
    }

    /*
     * Remove all Photoshop IPTC data from a JPEG file.
     */
    public void testRemove() throws Exception
    {
        List images = imagesWithIptcData;
        for (int i = 0; i < images.size(); i++)
        {
            if (i % 10 == 0)
                Debug.purgeMemory();

            File imageFile = (File) images.get(i);
            // Debug.debug("imageFile", imageFile);
            // Debug.debug();

            ByteSource byteSource = new ByteSourceFile(imageFile);

            Map params = new HashMap();
            boolean ignoreImageData = isPhilHarveyTestImage(imageFile);
            params
                    .put(PARAM_KEY_READ_THUMBNAILS, new Boolean(
                            !ignoreImageData));

            JpegPhotoshopMetadata metadata = new JpegImageParser()
                    .getPhotoshopMetadata(byteSource, params);
            assertNotNull(metadata);
            // metadata.dump();

            File noIptcFile = createTempFile(imageFile.getName()
                    + ".iptc.remove.", ".jpg");
            {
                // test remove

                OutputStream os = null;
                try
                {
                    os = new FileOutputStream(noIptcFile);
                    os = new BufferedOutputStream(os);
                    new JpegIptcRewriter().removeIPTC(byteSource, os);
                } finally
                {
                    if (os != null) {
                        os.close();
                    }
                    os = null;
                }

                JpegPhotoshopMetadata outMetadata = new JpegImageParser()
                        .getPhotoshopMetadata(new ByteSourceFile(noIptcFile),
                                params);
                assertTrue(outMetadata == null
                        || outMetadata.getItems().size() == 0);
            }

        }
    }

    public void testRemoveInsertUpdate() throws Exception
    {
        List images = imagesWithIptcData;
        for (int i = 0; i < images.size(); i++)
        {
            if (i % 10 == 0)
                Debug.purgeMemory();

            File imageFile = (File) images.get(i);
            Debug.debug("imageFile", imageFile);
            Debug.debug();

            ByteSource byteSource = new ByteSourceFile(imageFile);
            // Debug.debug("Segments:");
            // new JpegUtils().dumpJFIF(byteSource);

            Map params = new HashMap();
            boolean ignoreImageData = isPhilHarveyTestImage(imageFile);
            params
                    .put(PARAM_KEY_READ_THUMBNAILS, new Boolean(
                            !ignoreImageData));
            // params.put(PARAM_KEY_VERBOSE, Boolean.TRUE);
            // params.put(PARAM_KEY_VERBOSE, Boolean.TRUE);

            JpegPhotoshopMetadata metadata = new JpegImageParser()
                    .getPhotoshopMetadata(byteSource, params);
            assertNotNull(metadata);
            metadata.dump();

            File noIptcFile = createTempFile(imageFile.getName()
                    + ".iptc.remove.", ".jpg");
            {
                // test remove

                OutputStream os = null;
                try
                {
                    os = new FileOutputStream(noIptcFile);
                    os = new BufferedOutputStream(os);
                    new JpegIptcRewriter().removeIPTC(byteSource, os);
                } finally
                {
                    if (os != null) {
                        os.close();
                    }
                    os = null;
                }

                // Debug.debug("Source Segments:");
                // new JpegUtils().dumpJFIF(new ByteSourceFile(noIptcFile));

                JpegPhotoshopMetadata outMetadata = new JpegImageParser()
                        .getPhotoshopMetadata(new ByteSourceFile(noIptcFile),
                                params);
                assertTrue(outMetadata == null
                        || outMetadata.getItems().size() == 0);
            }
            {
                // test no-change update

                List newBlocks = metadata.photoshopApp13Data.getNonIptcBlocks();
                List oldRecords = metadata.photoshopApp13Data.getRecords();
                List newRecords = new ArrayList();
                for (int j = 0; j < oldRecords.size(); j++)
                {
                    IptcRecord record = (IptcRecord) oldRecords.get(j);
                    if (record.iptcType != IptcTypes.CITY
                            && record.iptcType != IptcTypes.CREDIT)
                        newRecords.add(record);
                }

                newRecords.add(new IptcRecord(IptcTypes.CITY,
                        "Albany, NY"));
                newRecords.add(new IptcRecord(IptcTypes.CREDIT,
                        "William Sorensen"));

                PhotoshopApp13Data newData = new PhotoshopApp13Data(newRecords,
                        newBlocks);

                File updated = createTempFile(imageFile.getName()
                        + ".iptc.update.", ".jpg");
                OutputStream os = null;
                try
                {
                    os = new FileOutputStream(updated);
                    os = new BufferedOutputStream(os);
                    new JpegIptcRewriter().writeIPTC(byteSource, os, newData);
                } finally
                {
                    if (os != null) {
                        os.close();
                    }
                    os = null;
                }

                // Debug.debug("Source Segments:");
                // new JpegUtils().dumpJFIF(new ByteSourceFile(updated));

                ByteSource updateByteSource = new ByteSourceFile(updated);
                JpegPhotoshopMetadata outMetadata = new JpegImageParser()
                        .getPhotoshopMetadata(updateByteSource, params);

                // Debug.debug("outMetadata", outMetadata.toString());
                // Debug.debug("hasIptcSegment", new JpegImageParser()
                // .hasIptcSegment(updateByteSource));

                assertNotNull(outMetadata);
                assertTrue(outMetadata.getItems().size() == newRecords.size());
                // assertEquals(metadata.toString(), outMetadata.toString());
            }

            {
                // test update

                List newBlocks = metadata.photoshopApp13Data.getNonIptcBlocks();
                List newRecords = new ArrayList();

                newRecords.add(new IptcRecord(IptcTypes.CITY,
                        "Albany, NY"));
                newRecords.add(new IptcRecord(IptcTypes.CREDIT,
                        "William Sorensen"));

                PhotoshopApp13Data newData = new PhotoshopApp13Data(newRecords,
                        newBlocks);

                File updated = createTempFile(imageFile.getName()
                        + ".iptc.update.", ".jpg");
                OutputStream os = null;
                try
                {
                    os = new FileOutputStream(updated);
                    os = new BufferedOutputStream(os);
                    new JpegIptcRewriter().writeIPTC(byteSource, os, newData);
                } finally
                {
                    if (os != null) {
                        os.close();
                    }
                    os = null;
                }

                // Debug.debug("Source Segments:");
                // new JpegUtils().dumpJFIF(new ByteSourceFile(updated));

                ByteSource updateByteSource = new ByteSourceFile(updated);
                JpegPhotoshopMetadata outMetadata = new JpegImageParser()
                        .getPhotoshopMetadata(updateByteSource, params);

                // Debug.debug("outMetadata", outMetadata.toString());
                // Debug.debug("hasIptcSegment", new JpegImageParser()
                // .hasIptcSegment(updateByteSource));

                assertNotNull(outMetadata);
                assertTrue(outMetadata.getItems().size() == 2);
                // assertEquals(metadata.toString(), outMetadata.toString());
            }

            {
                // test insert

                List newBlocks = new ArrayList();
                List newRecords = new ArrayList();

                newRecords.add(new IptcRecord(IptcTypes.CITY,
                        "Albany, NY"));
                newRecords.add(new IptcRecord(IptcTypes.CREDIT,
                        "William Sorensen"));

                PhotoshopApp13Data newData = new PhotoshopApp13Data(newRecords,
                        newBlocks);

                File updated = createTempFile(imageFile.getName()
                        + ".iptc.insert.", ".jpg");
                OutputStream os = null;
                try
                {
                    os = new FileOutputStream(updated);
                    os = new BufferedOutputStream(os);
                    new JpegIptcRewriter().writeIPTC(new ByteSourceFile(
                            noIptcFile), os, newData);
                } finally
                {
                    if (os != null) {
                        os.close();
                    }
                    os = null;
                }

                // Debug.debug("Source Segments:");
                // new JpegUtils().dumpJFIF(new ByteSourceFile(updated));

                ByteSource updateByteSource = new ByteSourceFile(updated);
                JpegPhotoshopMetadata outMetadata = new JpegImageParser()
                        .getPhotoshopMetadata(updateByteSource, params);

                // Debug.debug("outMetadata", outMetadata.toString());
                // Debug.debug("hasIptcSegment", new JpegImageParser()
                // .hasIptcSegment(updateByteSource));

                assertNotNull(outMetadata);
                assertTrue(outMetadata.getItems().size() == 2);
                // assertEquals(metadata.toString(), outMetadata.toString());
            }

        }
    }

    /*
     * Add a few IPTC values to JPEG images, whether or not they have existing
     * IPTC data.
     */
    public void testAddIptcData() throws Exception
    {
        List images = getJpegImages();
        for (int i = 0; i < images.size(); i++)
        {
            if (i % 10 == 0)
                Debug.purgeMemory();

            File imageFile = (File) images.get(i);
//             Debug.debug("imageFile", imageFile);
//             Debug.debug();

            ByteSource byteSource = new ByteSourceFile(imageFile);
//             Debug.debug("Segments:");
//             new JpegUtils().dumpJFIF(byteSource);

            Map params = new HashMap();
            boolean ignoreImageData = isPhilHarveyTestImage(imageFile);
            params
                    .put(PARAM_KEY_READ_THUMBNAILS, new Boolean(
                            !ignoreImageData));

            JpegPhotoshopMetadata metadata = new JpegImageParser()
                    .getPhotoshopMetadata(byteSource, params);
            // metadata.dump();

            {
                List newBlocks = new ArrayList();
                List newRecords = new ArrayList();

                if (null != metadata)
                {
                    boolean keepOldIptcNonTextValues = true;
                    if (keepOldIptcNonTextValues)
                        newBlocks.addAll(metadata.photoshopApp13Data
                                .getNonIptcBlocks());
                    boolean keepOldIptcTextValues = true;
                    if (keepOldIptcTextValues)
                    {
                        List oldRecords = metadata.photoshopApp13Data
                                .getRecords();

                        newRecords = new ArrayList();
                        for (int j = 0; j < oldRecords.size(); j++)
                        {
                            IptcRecord record = (IptcRecord) oldRecords.get(j);
                            if (record.iptcType != IptcTypes.CITY
                                    && record.iptcType != IptcTypes.CREDIT)
                                newRecords.add(record);
                        }
                    }
                }

                newRecords.add(new IptcRecord(IptcTypes.CITY,
                        "Albany, NY"));
                newRecords.add(new IptcRecord(IptcTypes.CREDIT,
                        "William Sorensen"));

                PhotoshopApp13Data newData = new PhotoshopApp13Data(newRecords,
                        newBlocks);

                File updated = createTempFile(imageFile.getName()
                        + ".iptc.add.", ".jpg");
                OutputStream os = null;
                try
                {
                    os = new FileOutputStream(updated);
                    os = new BufferedOutputStream(os);
                    new JpegIptcRewriter().writeIPTC(byteSource, os, newData);
                } finally
                {
                    if (os != null) {
                        os.close();
                    }
                    os = null;
                }

                // Debug.debug("Destination Segments:");
                // new JpegUtils().dumpJFIF(new ByteSourceFile(updated));

                ByteSource updateByteSource = new ByteSourceFile(updated);
                JpegPhotoshopMetadata outMetadata = new JpegImageParser()
                        .getPhotoshopMetadata(updateByteSource, params);

                // Debug.debug("outMetadata", outMetadata.toString());
                // Debug.debug("hasIptcSegment", new JpegImageParser()
                // .hasIptcSegment(updateByteSource));

                assertNotNull(outMetadata);
                assertTrue(outMetadata.getItems().size() == newRecords.size());
                // assertEquals(metadata.toString(), outMetadata.toString());
            }

        }
    }

}
