/*
 * Copyright (C) 2012 The Android Open Source Project
 *
 * Licensed 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 com.android.gallery3d.exif;

import android.test.suitebuilder.annotation.MediumTest;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel.MapMode;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ExifModifierTest extends ExifXmlDataTestCase {

    private File mTmpFile;
    private List<Map<Short, List<String>>> mGroundTruth;
    private ExifInterface mInterface;
    private Map<Short, ExifTag> mTestTags;
    ExifTag mVersionTag;
    ExifTag mGpsVersionTag;
    ExifTag mModelTag;
    ExifTag mDateTimeTag;
    ExifTag mCompressionTag;
    ExifTag mThumbnailFormatTag;
    ExifTag mLongitudeTag;
    ExifTag mShutterTag;

    @Override
    public void setUp() throws Exception {
        super.setUp();
        mGroundTruth = ExifXmlReader.readXml(getXmlParser());
        mTmpFile = File.createTempFile("exif_test", ".jpg");
        FileOutputStream os = null;
        InputStream is = getImageInputStream();
        try {
            os = new FileOutputStream(mTmpFile);
            byte[] buf = new byte[1024];
            int n;
            while ((n = is.read(buf)) > 0) {
                os.write(buf, 0, n);
            }
        } finally {
            Util.closeSilently(os);
        }

        // TYPE_UNDEFINED with 4 components
        mVersionTag = mInterface.buildTag(ExifInterface.TAG_EXIF_VERSION, new byte[] {
                1, 2, 3, 4
        });
        // TYPE_UNSIGNED_BYTE with 4 components
        mGpsVersionTag = mInterface.buildTag(ExifInterface.TAG_GPS_VERSION_ID, new byte[] {
                4, 3, 2, 1
        });
        // TYPE ASCII with arbitary length
        mModelTag = mInterface.buildTag(ExifInterface.TAG_MODEL, "end-of-the-world");
        // TYPE_ASCII with 20 components
        mDateTimeTag = mInterface.buildTag(ExifInterface.TAG_DATE_TIME, "2012:12:31 23:59:59");
        // TYPE_UNSIGNED_SHORT with 1 components
        mCompressionTag = mInterface.buildTag(ExifInterface.TAG_COMPRESSION, 100);
        // TYPE_UNSIGNED_LONG with 1 components
        mThumbnailFormatTag =
                mInterface.buildTag(ExifInterface.TAG_JPEG_INTERCHANGE_FORMAT, 100);
        // TYPE_UNSIGNED_RATIONAL with 3 components
        mLongitudeTag = mInterface.buildTag(ExifInterface.TAG_GPS_LONGITUDE, new Rational[] {
                new Rational(1, 1), new Rational(10, 10),
                new Rational(100, 100)
        });
        // TYPE_RATIONAL with 1 components
        mShutterTag = mInterface
                .buildTag(ExifInterface.TAG_SHUTTER_SPEED_VALUE, new Rational(1, 1));

        mTestTags = new HashMap<Short, ExifTag>();

        mTestTags.put(mVersionTag.getTagId(), mVersionTag);
        mTestTags.put(mGpsVersionTag.getTagId(), mGpsVersionTag);
        mTestTags.put(mModelTag.getTagId(), mModelTag);
        mTestTags.put(mDateTimeTag.getTagId(), mDateTimeTag);
        mTestTags.put(mCompressionTag.getTagId(), mCompressionTag);
        mTestTags.put(mThumbnailFormatTag.getTagId(), mThumbnailFormatTag);
        mTestTags.put(mLongitudeTag.getTagId(), mLongitudeTag);
        mTestTags.put(mShutterTag.getTagId(), mShutterTag);
    }

    public ExifModifierTest(int imageRes, int xmlRes) {
        super(imageRes, xmlRes);
        mInterface = new ExifInterface();
    }

    public ExifModifierTest(String imagePath, String xmlPath) {
        super(imagePath, xmlPath);
        mInterface = new ExifInterface();
    }

    @MediumTest
    public void testModify() throws Exception {
        Map<Short, Boolean> results = new HashMap<Short, Boolean>();

        RandomAccessFile file = null;
        try {
            file = new RandomAccessFile(mTmpFile, "rw");
            MappedByteBuffer buf = file.getChannel().map(MapMode.READ_WRITE, 0, file.length());
            for (ExifTag tag : mTestTags.values()) {
                ExifModifier modifier = new ExifModifier(buf, mInterface);
                modifier.modifyTag(tag);
                boolean result = modifier.commit();
                results.put(tag.getTagId(), result);
                buf.force();
                buf.position(0);

                if (!result) {
                    List<String> value = mGroundTruth.get(tag.getIfd()).get(tag.getTagId());
                    assertTrue(String.format("Tag %x, ", tag.getTagId()) + getImageTitle(),
                            value == null || tag.getTagId() == ExifInterface.TAG_MODEL);
                }
            }
        } finally {
            Util.closeSilently(file);
        }

        // Parse the new file and check the result
        InputStream is = null;
        try {
            is = new FileInputStream(mTmpFile);
            ExifData data = new ExifReader(mInterface).read(is);
            for (int i = 0; i < IfdId.TYPE_IFD_COUNT; i++) {
                checkIfd(data.getIfdData(i), mGroundTruth.get(i), results);
            }
        } finally {
            Util.closeSilently(is);
        }

    }

    private void checkIfd(IfdData ifd, Map<Short, List<String>> ifdValue,
            Map<Short, Boolean> results) {
        if (ifd == null) {
            assertEquals(getImageTitle(), 0, ifdValue.size());
            return;
        }
        ExifTag[] tags = ifd.getAllTags();
        for (ExifTag tag : tags) {
            List<String> truth = ifdValue.get(tag.getTagId());
            assertNotNull(String.format("Tag %x, ", tag.getTagId()) + getImageTitle(), truth);
            if (truth.contains(null)) {
                continue;
            }

            ExifTag newTag = mTestTags.get(tag.getTagId());
            if (newTag != null
                    && results.get(tag.getTagId())) {
                assertEquals(String.format("Tag %x, ", tag.getTagId()) + getImageTitle(),
                        Util.tagValueToString(newTag), Util.tagValueToString(tag));
            } else {
                assertTrue(String.format("Tag %x, ", tag.getTagId()) + getImageTitle(),
                        truth.contains(Util.tagValueToString(tag).trim()));
            }
        }
        assertEquals(getImageTitle(), ifdValue.size(), tags.length);
    }

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