/*
 * 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.imaging.formats.jpeg.exif;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Set;

import org.apache.commons.imaging.ImageReadException;
import org.apache.commons.imaging.ImageWriteException;
import org.apache.commons.imaging.Sanselan;
import org.apache.commons.imaging.common.bytesource.ByteSource;
import org.apache.commons.imaging.common.bytesource.ByteSourceArray;
import org.apache.commons.imaging.common.bytesource.ByteSourceFile;
import org.apache.commons.imaging.formats.jpeg.JpegImageMetadata;
import org.apache.commons.imaging.formats.jpeg.JpegUtils;
import org.apache.commons.imaging.formats.jpeg.exif.ExifRewriter;
import org.apache.commons.imaging.formats.tiff.TiffField;
import org.apache.commons.imaging.formats.tiff.TiffImageMetadata;
import org.apache.commons.imaging.formats.tiff.constants.AllTagConstants;
import org.apache.commons.imaging.formats.tiff.constants.TiffFieldTypeConstants;
import org.apache.commons.imaging.formats.tiff.write.TiffOutputSet;
import org.apache.commons.imaging.util.Debug;
import org.apache.commons.imaging.util.IoUtils;

public class ExifRewriteTest extends ExifBaseTest implements AllTagConstants
{
    //    public ExifRewriteTest(String name)
    //    {
    //        super(name);
    //    }

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

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

            boolean ignoreImageData = isPhilHarveyTestImage(imageFile);
            if (ignoreImageData)
                continue;

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

            {
                JpegImageMetadata metadata = (JpegImageMetadata) Sanselan
                        .getMetadata(imageFile);
                //                assertNotNull(metadata.getExif());
            }

            {
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                new ExifRewriter().removeExifMetadata(byteSource, baos);
                byte bytes[] = baos.toByteArray();
                File tempFile = createTempFile("test", ".jpg");
                Debug.debug("tempFile", tempFile);
                IoUtils.writeToFile(bytes, tempFile);

                Debug.debug("Output Segments:");
                new JpegUtils().dumpJFIF(new ByteSourceArray(bytes));

                assertTrue(!hasExifData(tempFile));
            }
        }
    }

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

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

            boolean ignoreImageData = isPhilHarveyTestImage(imageFile);
            if (ignoreImageData)
                continue;

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

            JpegImageMetadata originalMetadata = (JpegImageMetadata) Sanselan
                    .getMetadata(imageFile);
            assertNotNull(originalMetadata);

            TiffImageMetadata oldExifMetadata = originalMetadata.getExif();
            assertNotNull(oldExifMetadata);

            ByteSource stripped;
            {
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                new ExifRewriter().removeExifMetadata(byteSource, baos);
                byte bytes[] = baos.toByteArray();
                File tempFile = createTempFile("removed", ".jpg");
                Debug.debug("tempFile", tempFile);
                IoUtils.writeToFile(bytes, tempFile);

                Debug.debug("Output Segments:");
                stripped = new ByteSourceArray(bytes);
                new JpegUtils().dumpJFIF(stripped);

                assertTrue(!hasExifData(tempFile));
            }

            {
                TiffOutputSet outputSet = oldExifMetadata.getOutputSet();
                //            outputSet.dump();

                ByteArrayOutputStream baos = new ByteArrayOutputStream();

                new ExifRewriter().updateExifMetadataLossy(stripped, baos,
                        outputSet);

                byte bytes[] = baos.toByteArray();
                File tempFile = createTempFile("inserted" + "_", ".jpg");
                Debug.debug("tempFile", tempFile);
                IoUtils.writeToFile(bytes, tempFile);

                Debug.debug("Output Segments:");
                new JpegUtils().dumpJFIF(new ByteSourceArray(bytes));

                //                assertTrue(!hasExifData(tempFile));

                JpegImageMetadata newMetadata = (JpegImageMetadata) Sanselan
                        .getMetadata(tempFile);
                assertNotNull(newMetadata);
                TiffImageMetadata newExifMetadata = newMetadata.getExif();
                assertNotNull(newExifMetadata);
                //                newMetadata.dump();

                compare(imageFile, oldExifMetadata, newExifMetadata);
            }

        }
    }

    private interface Rewriter
    {
        public void rewrite(ByteSource byteSource, OutputStream os,
                TiffOutputSet outputSet) throws ImageReadException,
                IOException, ImageWriteException;
    }

    private void rewrite(Rewriter rewriter, String name) throws IOException,
            ImageReadException, ImageWriteException
    {
        List images = getImagesWithExifData();
        for (int i = 0; i < images.size(); i++)
        {
            if(i%10==0)
            Debug.purgeMemory();

            File imageFile = (File) images.get(i);

            try
            {

                Debug.debug("imageFile", imageFile);

                boolean ignoreImageData = isPhilHarveyTestImage(imageFile);
                if (ignoreImageData)
                    continue;

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

                JpegImageMetadata oldMetadata = (JpegImageMetadata) Sanselan
                        .getMetadata(imageFile);
                if (null == oldMetadata)
                    continue;
                assertNotNull(oldMetadata);

                TiffImageMetadata oldExifMetadata = oldMetadata.getExif();
                if (null == oldExifMetadata)
                    continue;
                assertNotNull(oldExifMetadata);
                oldMetadata.dump();

                //            TiffImageMetadata tiffImageMetadata = metadata.getExif();
                //            Photoshop photoshop = metadata.getPhotoshop();

                TiffOutputSet outputSet = oldExifMetadata.getOutputSet();
                //            outputSet.dump();

                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                rewriter.rewrite(byteSource, baos, outputSet);
                byte bytes[] = baos.toByteArray();
                File tempFile = createTempFile(name + "_", ".jpg");
                Debug.debug("tempFile", tempFile);
                IoUtils.writeToFile(bytes, tempFile);

                Debug.debug("Output Segments:");
                new JpegUtils().dumpJFIF(new ByteSourceArray(bytes));

                //                assertTrue(!hasExifData(tempFile));

                JpegImageMetadata newMetadata = (JpegImageMetadata) Sanselan
                        .getMetadata(tempFile);
                assertNotNull(newMetadata);
                TiffImageMetadata newExifMetadata = newMetadata.getExif();
                assertNotNull(newExifMetadata);
                //                newMetadata.dump();

                compare(imageFile, oldExifMetadata, newExifMetadata);
            }
            catch (IOException e)
            {
                Debug.debug("imageFile", imageFile.getAbsoluteFile());
                Debug.debug(e);
                throw e;
            }
            catch (ImageReadException e)
            {
                Debug.debug("imageFile", imageFile.getAbsoluteFile());
                Debug.debug(e);
                throw e;
            }
            catch (ImageWriteException e)
            {
                Debug.debug("imageFile", imageFile.getAbsoluteFile());
                Debug.debug(e);
                // FIXME: this image has 28kB of Maker Notes, causing the APP1 segment
                // to go beyond 64kB, so ignore the exception this throws.
                if (!imageFile.getName().equalsIgnoreCase("Nikon D50 - 2007.12.19.n.DSC_3656.JPG")) {
                    throw e;
                }
            }

        }
    }

    public void testRewriteLossy() throws Exception
    {
        Rewriter rewriter = new Rewriter()
        {
            public void rewrite(ByteSource byteSource, OutputStream os,
                    TiffOutputSet outputSet) throws ImageReadException,
                    IOException, ImageWriteException
            {
                new ExifRewriter().updateExifMetadataLossy(byteSource, os,
                        outputSet);
            }
        };

        rewrite(rewriter, "lossy");
    }

    public void testRewriteLossless() throws Exception
    {
        Rewriter rewriter = new Rewriter()
        {
            public void rewrite(ByteSource byteSource, OutputStream os,
                    TiffOutputSet outputSet) throws ImageReadException,
                    IOException, ImageWriteException
            {
                new ExifRewriter().updateExifMetadataLossless(byteSource, os,
                        outputSet);
            }
        };

        rewrite(rewriter, "lossless");
    }

    private Hashtable makeDirectoryMap(List directories)
    {
        Hashtable directoryMap = new Hashtable();
        for (int i = 0; i < directories.size(); i++)
        {
            TiffImageMetadata.Directory directory = (TiffImageMetadata.Directory) directories
                    .get(i);
            directoryMap.put(new Integer(directory.type), directory);
        }
        return directoryMap;
    }

    private Hashtable makeFieldMap(List items)
    {
        Hashtable fieldMap = new Hashtable();
        for (int i = 0; i < items.size(); i++)
        {
            TiffImageMetadata.Item item = (TiffImageMetadata.Item) items.get(i);
            TiffField field = item.getTiffField();
            Object key = new Integer(field.tag);
            if (!fieldMap.containsKey(key))
                fieldMap.put(key, field);
        }
        return fieldMap;
    }

    private void compare(File imageFile, TiffImageMetadata oldExifMetadata,
            TiffImageMetadata newExifMetadata) throws ImageReadException
    {
        assertNotNull(oldExifMetadata);
        assertNotNull(newExifMetadata);

        List oldDirectories = oldExifMetadata.getDirectories();
        List newDirectories = newExifMetadata.getDirectories();

        assertTrue(oldDirectories.size() == newDirectories.size());

        Hashtable oldDirectoryMap = makeDirectoryMap(oldDirectories);
        Hashtable newDirectoryMap = makeDirectoryMap(newDirectories);

        assertEquals(oldDirectories.size(), oldDirectoryMap.keySet().size());
        List oldDirectoryTypes = new ArrayList(oldDirectoryMap.keySet());
        Collections.sort(oldDirectoryTypes);
        List newDirectoryTypes = new ArrayList(newDirectoryMap.keySet());
        Collections.sort(newDirectoryTypes);
        assertEquals(oldDirectoryTypes, newDirectoryTypes);

        for (int i = 0; i < oldDirectoryTypes.size(); i++)
        {
            Integer dirType = (Integer) oldDirectoryTypes.get(i);

            //            Debug.debug("dirType", dirType);

            TiffImageMetadata.Directory oldDirectory = (TiffImageMetadata.Directory) oldDirectoryMap
                    .get(dirType);
            TiffImageMetadata.Directory newDirectory = (TiffImageMetadata.Directory) newDirectoryMap
                    .get(dirType);
            assertNotNull(oldDirectory);
            assertNotNull(newDirectory);

            List oldItems = oldDirectory.getItems();
            List newItems = newDirectory.getItems();

            //            Debug.debug("oldItems.size()", oldItems.size());
            //            Debug.debug("newItems.size()", newItems.size());
            //            dump("oldItems", oldItems);
            //            dump("newItems", newItems);

            //            if (oldItems.size() != newItems.size())
            //                ;
            //            {
            //            dump("oldItems", oldItems);
            //            dump("newItems", newItems);
            //            }
            //            assertTrue(oldItems.size() == newItems.size());

            Hashtable oldFieldMap = makeFieldMap(oldItems);
            Hashtable newFieldMap = makeFieldMap(newItems);

            Set missingInNew = new HashSet(oldFieldMap.keySet());
            missingInNew.removeAll(newFieldMap.keySet());

            Set missingInOld = new HashSet(newFieldMap.keySet());
            missingInOld.removeAll(oldFieldMap.keySet());

            //            dump("missingInNew", missingInNew);
            //            dump("missingInOld", missingInOld);
            //            dump("newFieldMap.keySet()", newFieldMap.keySet());
            //            dump("oldFieldMap.keySet()", oldFieldMap.keySet());

            assertTrue(missingInNew.size() == 0);
            assertTrue(missingInOld.size() == 0);

            //            Debug.debug("oldItems.size()", oldItems.size());
            //            Debug.debug("oldFieldMap.keySet().size()", oldFieldMap.keySet().size());

            //            assertEquals(oldItems.size(), oldFieldMap.keySet().size());
            //            assertEquals(oldFieldMap.keySet(), newFieldMap.keySet());
            //            assertEquals(oldFieldMap.keySet(), newFieldMap.keySet());

            List oldFieldTags = new ArrayList(oldFieldMap.keySet());
            Collections.sort(oldFieldTags);
            List newFieldTags = new ArrayList(newFieldMap.keySet());
            Collections.sort(newFieldTags);
            assertEquals(oldFieldTags, newFieldTags);

            for (int j = 0; j < oldFieldTags.size(); j++)
            {
                Integer fieldTag = (Integer) oldFieldTags.get(j);

                TiffField oldField = (TiffField) oldFieldMap.get(fieldTag);
                TiffField newField = (TiffField) newFieldMap.get(fieldTag);

                //                Debug.debug("fieldTag", fieldTag);
                //                Debug.debug("oldField", oldField);
                //                Debug.debug("newField", newField);

                //                fieldTag.
                assertNotNull(oldField);
                assertNotNull(newField);

                assertEquals(oldField.tag, newField.tag);
                assertEquals(dirType.intValue(), newField.directoryType);
                assertEquals(oldField.directoryType, newField.directoryType);
                assertEquals(oldField.length, newField.length);
                assertEquals(oldField.isLocalValue(), newField.isLocalValue());

                if (oldField.tag == 0x202)
                {
                    // ignore "jpg from raw length" value. may have off-by-one bug in certain cameras.
                    // i.e. Sony DCR-PC110
                    continue;
                }

                if (oldField.fieldType == TiffFieldTypeConstants.FIELD_TYPE_ASCII)
                {
                    // Sanselan currently doesn't correctly rewrite
                    // strings if any byte had the highest bit set,
                    // so if the source had that, all bets are off.
                    byte[] rawBytes = oldField.fieldType.getRawBytes(oldField);
                    boolean hasInvalidByte = false;
                    for (int k = 0; k < rawBytes.length; k++)
                    {
                        if ((rawBytes[k] & 0x80) != 0)
                        {
                            hasInvalidByte = true;
                            break;
                        }
                    }
                    if (hasInvalidByte)
                        continue;
                }

                if (!oldField.tagInfo.isOffset())
                {
                    if (oldField.tagInfo.isText())
                    { /* do nothing */ }
                    else if (oldField.isLocalValue())
                    {
                        //                        Debug.debug("oldField.tag", oldField.tag);
                        //                        Debug.debug("newField.tag", newField.tag);
                        //                        Debug.debug("oldField.tagInfo", oldField.tagInfo);
                        //                        Debug.debug("newField.tagInfo", newField.tagInfo);
                        //                        Debug.debug("oldField.fieldType", oldField.fieldType);
                        //                        Debug.debug("newField.fieldType", newField.fieldType);
                        //                        Debug.debug("oldField.getBytesLength", oldField
                        //                                .getBytesLength());
                        //                        Debug.debug("newField.getBytesLength", newField
                        //                                .getBytesLength());
                        //
                        //                        Debug.debug("oldField.valueOffsetBytes",
                        //                                oldField.valueOffsetBytes);
                        //                        Debug.debug("newField.valueOffsetBytes",
                        //                                newField.valueOffsetBytes);

                        String label = imageFile.getName() + 
                                       ", dirType[" + i + "]=" + dirType +
                                       ", fieldTag[" + j + "]=" + fieldTag;
                        if (oldField.tag == 0x116 || oldField.tag == 0x117)
                            compare(label, oldField, newField);
                        else {
                            compare(label, oldField.valueOffsetBytes,
                                           newField.valueOffsetBytes,
                                           oldField.getBytesLength(),
                                           newField.getBytesLength());
                        }
                    }
                    else
                    {
                        //                        Debug.debug("oldField.tagInfo", oldField.tagInfo);
                        //                        Debug.debug("oldField.fieldType", oldField.fieldType);
                        //                        Debug.debug("newField.fieldType", newField.fieldType);
                        //                        Debug.debug("oldField.getBytesLength", oldField
                        //                                .getBytesLength());
                        //                        Debug.debug("newField.getBytesLength", newField
                        //                                .getBytesLength());

                        //                        Debug.debug("oldField.oversizeValue", oldField.oversizeValue);
                        //                        Debug.debug("newField.oversizeValue", newField.oversizeValue);

                        compare(oldField.oversizeValue, newField.oversizeValue);
                    }
                }

            }

            //            Debug.debug();
        }
    }

    private void compare(String label, byte a[], byte b[], int aLength, int bLength)
    {
        //        Debug.debug("c0 a", a);
        //        Debug.debug("c0 b", b);
        assertEquals(aLength, bLength);
        assertTrue(a.length >= aLength);
        assertTrue(b.length >= bLength);
        assertNotNull(a);
        assertNotNull(b);
        assertEquals(a.length, b.length);
        int length = aLength;
        for (int i = 0; i < length; i++)
        {
            //            byte ba = a[i];
            //            byte bb = b[i];
            //            boolean eq = ba == bb;
            //            Debug.debug("i: " + i + ", a[i]: " + ba + ", b[i]: " + bb + " = "
            //                    + (ba == bb) + " " + eq);
            //            if(ba != bb)
            //                assertFalse(true);
            //
            //            Debug.debug("i: " + i + ", a[i]: " + ba + ", b[i]: " + bb + " = "
            //                    + (ba == bb) + " " + eq);
            //            assertTrue(eq == true);
            assertEquals(label + ", byte[" + i + "]", a[i], b[i]);
            //            Debug.debug("c");
            //            assertTrue((0xff & a[i]) == (0xff & b[i]));
        }
    }

    private void compare(String label, TiffField a, TiffField b) throws ImageReadException
    {
        Object v1 = a.getValue();
        Object v2 = b.getValue();

        //        Debug.debug("v1", v1 + " (" + Debug.getType(v1) + ")");
        //        Debug.debug("v2", v2 + " (" + Debug.getType(v2) + ")");
        assertEquals(label, v1, v2);
    }

    private void compare(byte a[], byte b[])
    {
        //        Debug.debug("c1 a", a);
        //        Debug.debug("c1 b", b);
        assertNotNull(a);
        assertNotNull(b);
        assertEquals(a.length, b.length);
        for (int i = 0; i < a.length; i++)
            assertEquals(a[i], b[i]);
    }
}
