/*
 * 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.tiff;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.sanselan.FormatCompliance;
import org.apache.commons.sanselan.ImageReadException;
import org.apache.commons.sanselan.common.BinaryFileParser;
import org.apache.commons.sanselan.common.bytesource.ByteSource;
import org.apache.commons.sanselan.formats.tiff.TiffDirectory.ImageDataElement;
import org.apache.commons.sanselan.formats.tiff.constants.ExifTagConstants;
import org.apache.commons.sanselan.formats.tiff.constants.TiffConstants;
import org.apache.commons.sanselan.formats.tiff.constants.TiffTagConstants;
import org.apache.commons.sanselan.util.Debug;

public class TiffReader extends BinaryFileParser implements TiffConstants
{

    private final boolean strict;

    public TiffReader(boolean strict)
    {
        this.strict = strict;
    }

    private TiffHeader readTiffHeader(ByteSource byteSource,
            FormatCompliance formatCompliance) throws ImageReadException,
            IOException
    {
        InputStream is = null;
        try
        {
            is = byteSource.getInputStream();
            return readTiffHeader(is, formatCompliance);
        } finally
        {
            try
            {
                if (is != null)
                    is.close();
            } catch (Exception e)
            {
                Debug.debug(e);
            }
        }
    }

    private TiffHeader readTiffHeader(InputStream is,
            FormatCompliance formatCompliance) throws ImageReadException,
            IOException
    {
        int BYTE_ORDER_1 = readByte("BYTE_ORDER_1", is, "Not a Valid TIFF File");
        int BYTE_ORDER_2 = readByte("BYTE_ORDER_2", is, "Not a Valid TIFF File");
        setByteOrder(BYTE_ORDER_1, BYTE_ORDER_2);

        int tiffVersion = read2Bytes("tiffVersion", is, "Not a Valid TIFF File");
        if (tiffVersion != 42)
            throw new ImageReadException("Unknown Tiff Version: " + tiffVersion);

        int offsetToFirstIFD = read4Bytes("offsetToFirstIFD", is,
                "Not a Valid TIFF File");

        skipBytes(is, offsetToFirstIFD - 8,
                "Not a Valid TIFF File: couldn't find IFDs");

        if (debug)
            System.out.println("");

        return new TiffHeader(BYTE_ORDER_1, tiffVersion, offsetToFirstIFD);
    }

    private void readDirectories(ByteSource byteSource,
            FormatCompliance formatCompliance, Listener listener)
            throws ImageReadException, IOException
    {
        TiffHeader tiffHeader = readTiffHeader(byteSource, formatCompliance);
        if (!listener.setTiffHeader(tiffHeader))
            return;

        int offset = tiffHeader.offsetToFirstIFD;
        int dirType = TiffDirectory.DIRECTORY_TYPE_ROOT;

        List<Number> visited = new ArrayList<Number>();
        readDirectory(byteSource, offset, dirType, formatCompliance, listener,
                visited);
    }

    private boolean readDirectory(ByteSource byteSource, int offset,
            int dirType, FormatCompliance formatCompliance, Listener listener,
            List<Number> visited) throws ImageReadException, IOException
    {
        boolean ignoreNextDirectory = false;
        return readDirectory(byteSource, offset, dirType, formatCompliance,
                listener, ignoreNextDirectory, visited);
    }

    private boolean readDirectory(ByteSource byteSource, int offset,
            int dirType, FormatCompliance formatCompliance, Listener listener,
            boolean ignoreNextDirectory, List<Number> visited)
            throws ImageReadException, IOException
    {

        // Debug.debug();
        // Debug.debug("dir offset", offset + " (0x" +
        // Integer.toHexString(offset)
        // + ")");
        // Debug.debug("dir key", key);
        // Debug.debug("dir visited", visited);
        // Debug.debug("dirType", dirType);
        // Debug.debug();

        if (visited.contains(offset))
            return false;
        visited.add(offset);

        InputStream is = null;
        try
        {
            if (offset >= byteSource.getLength())
            {
                // Debug.debug("skipping invalid directory!");
                return true;
            }

            is = byteSource.getInputStream();
            skipBytes(is, offset);

            List<TiffField> fields = new ArrayList<TiffField>();

            int entryCount;
            try
            {
                entryCount = read2Bytes("DirectoryEntryCount", is,
                        "Not a Valid TIFF File");
            } catch (IOException e)
            {
                if (strict)
                    throw e;
                else
                    return true;
            }

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

            for (int i = 0; i < entryCount; i++)
            {
                int tag = read2Bytes("Tag", is, "Not a Valid TIFF File");
                int type = read2Bytes("Type", is, "Not a Valid TIFF File");
                int length = read4Bytes("Length", is, "Not a Valid TIFF File");

                // Debug.debug("tag*", tag + " (0x" + Integer.toHexString(tag)
                // + ")");

                byte valueOffsetBytes[] = readByteArray("ValueOffset", 4, is,
                        "Not a Valid TIFF File");
                int valueOffset = convertByteArrayToInt("ValueOffset",
                        valueOffsetBytes);

                if (tag == 0)
                {
                    // skip invalid fields.
                    // These are seen very rarely, but can have invalid value
                    // lengths,
                    // which can cause OOM problems.
                    continue;
                }

                // if (keepField(tag, tags))
                // {
                TiffField field = new TiffField(tag, dirType, type, length,
                        valueOffset, valueOffsetBytes, getByteOrder());
                field.setSortHint(i);

                // Debug.debug("tagInfo", field.tagInfo);

                try {
                    field.fillInValue(byteSource);
                } catch (TiffValueOutsideFileBoundsException valueOutsideFileException) {
                    if (strict) {
                        // Java 1.5+ throw new IOException(valueOutsideFileException);
                        IOException ioe = new IOException();
                        ioe.initCause(valueOutsideFileException);
                        throw ioe;
                    } else {
                        // corrupt field, ignore it
                        continue;
                    }
                }

                // Debug.debug("\t" + "value", field.getValueDescription());

                fields.add(field);

                if (!listener.addField(field))
                    return true;
            }

            int nextDirectoryOffset = read4Bytes("nextDirectoryOffset", is,
                    "Not a Valid TIFF File");
            // Debug.debug("nextDirectoryOffset", nextDirectoryOffset);

            TiffDirectory directory = new TiffDirectory(dirType, fields,
                    offset, nextDirectoryOffset);

            if (listener.readImageData())
            {
                if (directory.hasTiffImageData())
                {
                    TiffImageData rawImageData = getTiffRawImageData(
                            byteSource, directory);
                    directory.setTiffImageData(rawImageData);
                }
                if (directory.hasJpegImageData())
                {
                    JpegImageData rawJpegImageData = getJpegRawImageData(
                            byteSource, directory);
                    directory.setJpegImageData(rawJpegImageData);
                }
            }

            if (!listener.addDirectory(directory))
                return true;

            if (listener.readOffsetDirectories())
            {
                List<TiffField> fieldsToRemove = new ArrayList<TiffField>();
                for (int j = 0; j < fields.size(); j++)
                {
                    TiffField entry = fields.get(j);

                    if (entry.tag == ExifTagConstants.EXIF_TAG_EXIF_OFFSET.tag
                            || entry.tag == ExifTagConstants.EXIF_TAG_GPSINFO.tag
                            || entry.tag == ExifTagConstants.EXIF_TAG_INTEROP_OFFSET.tag)
                    { /* do nothing */ }
                    else
                        continue;

                    int subDirectoryOffset = ((Number) entry.getValue())
                            .intValue();
                    int subDirectoryType;
                    if (entry.tag == ExifTagConstants.EXIF_TAG_EXIF_OFFSET.tag)
                        subDirectoryType = TiffDirectory.DIRECTORY_TYPE_EXIF;
                    else if (entry.tag == ExifTagConstants.EXIF_TAG_GPSINFO.tag)
                        subDirectoryType = TiffDirectory.DIRECTORY_TYPE_GPS;
                    else if (entry.tag == ExifTagConstants.EXIF_TAG_INTEROP_OFFSET.tag)
                        subDirectoryType = TiffDirectory.DIRECTORY_TYPE_INTEROPERABILITY;
                    else
                        throw new ImageReadException(
                                "Unknown subdirectory type.");

                    // Debug.debug("sub dir", subDirectoryOffset);
                    boolean subDirectoryRead = readDirectory(byteSource,
                            subDirectoryOffset, subDirectoryType,
                            formatCompliance, listener, true, visited);

                    if (!subDirectoryRead)
                    {
                        // Offset field pointed to invalid location.
                        // This is a bug in certain cameras. Ignore offset
                        // field.
                        fieldsToRemove.add(entry);
                    }

                }
                fields.removeAll(fieldsToRemove);
            }

            if (!ignoreNextDirectory && directory.nextDirectoryOffset > 0)
            {
                // Debug.debug("next dir", directory.nextDirectoryOffset );
                readDirectory(byteSource, directory.nextDirectoryOffset,
                        dirType + 1, formatCompliance, listener, visited);
            }

            return true;
        } finally
        {
            try
            {
                if (is != null)
                    is.close();
            } catch (Exception e)
            {
                Debug.debug(e);
            }
        }
    }

    public static interface Listener
    {
        public boolean setTiffHeader(TiffHeader tiffHeader);

        public boolean addDirectory(TiffDirectory directory);

        public boolean addField(TiffField field);

        public boolean readImageData();

        public boolean readOffsetDirectories();
    }

    private static class Collector implements Listener
    {
        private TiffHeader tiffHeader = null;
        private List<TiffDirectory> directories = new ArrayList<TiffDirectory>();
        private List<TiffField> fields = new ArrayList<TiffField>();
        private final boolean readThumbnails;

        public Collector()
        {
            this(null);
        }

        public Collector(Map params)
        {
            boolean readThumbnails = true;
            if (params != null && params.containsKey(PARAM_KEY_READ_THUMBNAILS))
                readThumbnails = Boolean.TRUE.equals(params
                        .get(PARAM_KEY_READ_THUMBNAILS));
            this.readThumbnails = readThumbnails;
        }

        public boolean setTiffHeader(TiffHeader tiffHeader)
        {
            this.tiffHeader = tiffHeader;
            return true;
        }

        public boolean addDirectory(TiffDirectory directory)
        {
            directories.add(directory);
            return true;
        }

        public boolean addField(TiffField field)
        {
            fields.add(field);
            return true;
        }

        public boolean readImageData()
        {
            return readThumbnails;
        }

        public boolean readOffsetDirectories()
        {
            return true;
        }

        public TiffContents getContents()
        {
            return new TiffContents(tiffHeader, directories);
        }
    }

    private static class FirstDirectoryCollector extends Collector
    {
        private final boolean readImageData;

        public FirstDirectoryCollector(final boolean readImageData)
        {
            this.readImageData = readImageData;
        }

        @Override
        public boolean addDirectory(TiffDirectory directory)
        {
            super.addDirectory(directory);
            return false;
        }

        @Override
        public boolean readImageData()
        {
            return readImageData;
        }
    }

    private static class DirectoryCollector extends Collector
    {
        private final boolean readImageData;

        public DirectoryCollector(final boolean readImageData)
        {
            this.readImageData = readImageData;
        }

        @Override
        public boolean addDirectory(TiffDirectory directory)
        {
            super.addDirectory(directory);
            return false;
        }

        @Override
        public boolean readImageData()
        {
            return readImageData;
        }
    }

    public TiffContents readFirstDirectory(ByteSource byteSource, Map params,
            boolean readImageData, FormatCompliance formatCompliance)
            throws ImageReadException, IOException
    {
        Collector collector = new FirstDirectoryCollector(readImageData);
        read(byteSource, params, formatCompliance, collector);
        TiffContents contents = collector.getContents();
        if (contents.directories.size() < 1)
            throw new ImageReadException(
                    "Image did not contain any directories.");
        return contents;
    }

    public TiffContents readDirectories(ByteSource byteSource,
            boolean readImageData, FormatCompliance formatCompliance)
            throws ImageReadException, IOException
    {
        Collector collector = new Collector(null);
        readDirectories(byteSource, formatCompliance, collector);
        TiffContents contents = collector.getContents();
        if (contents.directories.size() < 1)
            throw new ImageReadException(
                    "Image did not contain any directories.");
        return contents;
    }

    public TiffContents readContents(ByteSource byteSource, Map params,
            FormatCompliance formatCompliance) throws ImageReadException,
            IOException
    {

        Collector collector = new Collector(params);
        read(byteSource, params, formatCompliance, collector);
        TiffContents contents = collector.getContents();
        return contents;
    }

    public void read(ByteSource byteSource, Map params,
            FormatCompliance formatCompliance, Listener listener)
            throws ImageReadException, IOException
    {
        // TiffContents contents =
        readDirectories(byteSource, formatCompliance, listener);
    }

    private TiffImageData getTiffRawImageData(ByteSource byteSource,
            TiffDirectory directory) throws ImageReadException, IOException
    {

        List<ImageDataElement> elements = directory.getTiffRawImageDataElements();
        TiffImageData.Data data[] = new TiffImageData.Data[elements.size()];
        for (int i = 0; i < elements.size(); i++)
        {
            TiffDirectory.ImageDataElement element = elements.get(i);
            byte bytes[] = byteSource.getBlock(element.offset, element.length);
            data[i] = new TiffImageData.Data(element.offset, element.length,
                    bytes);
        }

        if (directory.imageDataInStrips())
        {
            TiffField rowsPerStripField = directory
                    .findField(TiffTagConstants.TIFF_TAG_ROWS_PER_STRIP);
            int rowsPerStrip ; 

            if (null != rowsPerStripField) {
                rowsPerStrip = rowsPerStripField.getIntValue();
            } else {
                TiffField imageHeight = directory.findField(TiffTagConstants.TIFF_TAG_IMAGE_LENGTH);
                /**
                 * if rows per strip not present then rowsPerStrip 
                 * is equal to imageLength or an infinity value;
                 */
                rowsPerStrip = imageHeight.getIntValue();           
            }

            return new TiffImageData.Strips(data, rowsPerStrip);
        } else
        {
            TiffField tileWidthField = directory.findField(TiffTagConstants.TIFF_TAG_TILE_WIDTH);
            if (null == tileWidthField)
                throw new ImageReadException("Can't find tile width field.");
            int tileWidth = tileWidthField.getIntValue();

            TiffField tileLengthField = directory
                    .findField(TiffTagConstants.TIFF_TAG_TILE_LENGTH);
            if (null == tileLengthField)
                throw new ImageReadException("Can't find tile length field.");
            int tileLength = tileLengthField.getIntValue();

            return new TiffImageData.Tiles(data, tileWidth, tileLength);
        }
    }

    private JpegImageData getJpegRawImageData(ByteSource byteSource,
            TiffDirectory directory) throws ImageReadException, IOException
    {
        ImageDataElement element = directory.getJpegRawImageDataElement();
        int offset = element.offset;
        int length = element.length;
        // Sony DCR-PC110 has an off-by-one error.
        if (offset + length == byteSource.getLength() + 1)
            length--;
        byte data[] = byteSource.getBlock(offset, length);
        return new JpegImageData(offset, length, data);
    }

}
