/*
 * 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.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.imaging.FormatCompliance;
import org.apache.commons.imaging.ImageReadException;
import org.apache.commons.imaging.common.BinaryFileParser;
import org.apache.commons.imaging.common.bytesource.ByteSource;
import org.apache.commons.imaging.formats.tiff.TiffDirectory.ImageDataElement;
import org.apache.commons.imaging.formats.tiff.constants.ExifTagConstants;
import org.apache.commons.imaging.formats.tiff.constants.TiffConstants;
import org.apache.commons.imaging.formats.tiff.constants.TiffTagConstants;
import org.apache.commons.imaging.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);
    }

}
