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

import java.io.IOException;
import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.Map;

import javax.imageio.stream.ImageInputStream;

import org.apache.pdfbox.jbig2.io.SubInputStream;
import org.apache.pdfbox.jbig2.segments.EndOfStripe;
import org.apache.pdfbox.jbig2.segments.GenericRefinementRegion;
import org.apache.pdfbox.jbig2.segments.GenericRegion;
import org.apache.pdfbox.jbig2.segments.HalftoneRegion;
import org.apache.pdfbox.jbig2.segments.PageInformation;
import org.apache.pdfbox.jbig2.segments.PatternDictionary;
import org.apache.pdfbox.jbig2.segments.Profiles;
import org.apache.pdfbox.jbig2.segments.SymbolDictionary;
import org.apache.pdfbox.jbig2.segments.Table;
import org.apache.pdfbox.jbig2.segments.TextRegion;
import org.apache.pdfbox.jbig2.util.log.Logger;
import org.apache.pdfbox.jbig2.util.log.LoggerFactory;

/**
 * The basic class for all JBIG2 segments.
 */
@SuppressWarnings("unchecked")
public class SegmentHeader
{
    private static final Logger log = LoggerFactory.getLogger(SegmentHeader.class);

    private static final Map<Integer, Class<? extends SegmentData>> SEGMENT_TYPE_MAP = new HashMap<Integer, Class<? extends SegmentData>>();

    static
    {
        Object SEGMENT_TYPES[][] = { { 0, SymbolDictionary.class }, { 4, TextRegion.class },
                { 6, TextRegion.class }, { 7, TextRegion.class }, { 16, PatternDictionary.class },
                { 20, HalftoneRegion.class }, { 22, HalftoneRegion.class },
                { 23, HalftoneRegion.class }, { 36, GenericRegion.class },
                { 38, GenericRegion.class }, { 39, GenericRegion.class },
                { 40, GenericRefinementRegion.class }, { 42, GenericRefinementRegion.class },
                { 43, GenericRefinementRegion.class }, { 48, PageInformation.class },
                { 50, EndOfStripe.class }, { 52, Profiles.class }, { 53, Table.class }, };

        for (int i = 0; i < SEGMENT_TYPES.length; i++)
        {
            Object[] objects = SEGMENT_TYPES[i];
            SEGMENT_TYPE_MAP.put((Integer) objects[0], (Class<? extends SegmentData>) objects[1]);
        }
    }

    private int segmentNr;
    private int segmentType;
    private byte retainFlag;
    private int pageAssociation;
    private byte pageAssociationFieldSize;
    private SegmentHeader[] rtSegments;
    private long segmentHeaderLength;
    private long segmentDataLength;
    private long segmentDataStartOffset;
    private final SubInputStream subInputStream;

    private Reference<SegmentData> segmentData;

    public SegmentHeader(JBIG2Document document, SubInputStream sis, long offset,
            int organisationType) throws IOException
    {
        this.subInputStream = sis;
        parse(document, sis, offset, organisationType);
    }

    /**
     * 
     * 
     * @param document
     * @param subInputStream
     * @param organisationType
     * @param offset - The offset where the segment header starts
     * @throws IOException
     */
    private void parse(JBIG2Document document, ImageInputStream subInputStream, long offset,
            int organisationType) throws IOException
    {

        printDebugMessage("\n########################");
        printDebugMessage("Segment parsing started.");

        subInputStream.seek(offset);
        printDebugMessage("|-Seeked to offset: " + offset);

        /* 7.2.2 Segment number */
        readSegmentNumber(subInputStream);

        /* 7.2.3 Segment header flags */
        readSegmentHeaderFlag(subInputStream);

        /* 7.2.4 Amount of referred-to segments */
        int countOfRTS = readAmountOfReferredToSegments(subInputStream);

        /* 7.2.5 Referred-to segments numbers */
        int[] rtsNumbers = readReferredToSegmentsNumbers(subInputStream, countOfRTS);

        /* 7.2.6 Segment page association (Checks how big the page association field is.) */
        readSegmentPageAssociation(document, subInputStream, countOfRTS, rtsNumbers);

        /* 7.2.7 Segment data length (Contains the length of the data part (in bytes).) */
        readSegmentDataLength(subInputStream);

        readDataStartOffset(subInputStream, organisationType);
        readSegmentHeaderLength(subInputStream, offset);
        printDebugMessage("########################\n");
    }

    /**
     * 7.2.2 Segment number
     * 
     * @param subInputStream
     * @throws IOException
     */
    private void readSegmentNumber(ImageInputStream subInputStream) throws IOException
    {
        segmentNr = (int) (subInputStream.readBits(32) & 0xffffffff);
        printDebugMessage("|-Segment Nr: " + segmentNr);
    }

    /**
     * 7.2.3 Segment header flags
     * 
     * @param subInputStream
     * @throws IOException
     */
    private void readSegmentHeaderFlag(ImageInputStream subInputStream) throws IOException
    {
        // Bit 7: Retain Flag, if 1, this segment is flagged as retained;
        retainFlag = (byte) subInputStream.readBit();
        printDebugMessage("|-Retain flag: " + retainFlag);

        // Bit 6: Size of the page association field. One byte if 0, four bytes if 1;
        pageAssociationFieldSize = (byte) subInputStream.readBit();
        printDebugMessage("|-Page association field size=" + pageAssociationFieldSize);

        // Bit 5-0: Contains the values (between 0 and 62 with gaps) for segment types, specified in 7.3
        segmentType = (int) (subInputStream.readBits(6) & 0xff);
        printDebugMessage("|-Segment type=" + segmentType);
    }

    /**
     * 7.2.4 Amount of referred-to segments
     * 
     * @param subInputStream
     * @return The amount of referred-to segments.
     * @throws IOException
     */
    private int readAmountOfReferredToSegments(ImageInputStream subInputStream) throws IOException
    {
        int countOfRTS = (int) (subInputStream.readBits(3) & 0xf);
        printDebugMessage("|-RTS count: " + countOfRTS);

        byte[] retainBit;

        printDebugMessage("  |-Stream position before RTS: " + subInputStream.getStreamPosition());

        if (countOfRTS <= 4)
        {
            /* short format */
            retainBit = new byte[5];
            for (int i = 0; i <= 4; i++)
            {
                retainBit[i] = (byte) subInputStream.readBit();
            }
        }
        else
        {
            /* long format */
            countOfRTS = (int) (subInputStream.readBits(29) & 0xffffffff);

            int arrayLength = (countOfRTS + 8) >> 3;
            retainBit = new byte[arrayLength <<= 3];

            for (int i = 0; i < arrayLength; i++)
            {
                retainBit[i] = (byte) subInputStream.readBit();
            }
        }

        printDebugMessage("  |-Stream position after RTS: " + subInputStream.getStreamPosition());

        return countOfRTS;
    }

    /**
     * 7.2.5 Referred-to segments numbers
     * <p>
     * Gathers all segment numbers of referred-to segments. The segments itself are stored in the {@link #rtSegments}
     * array.
     * 
     * @param subInputStream - Wrapped source data input stream.
     * @param countOfRTS - The amount of referred-to segments.
     * 
     * @return An array with the segment number of all referred-to segments.
     * 
     * @throws IOException
     */
    private int[] readReferredToSegmentsNumbers(ImageInputStream subInputStream, int countOfRTS)
            throws IOException
    {
        int[] rtsNumbers = new int[countOfRTS];

        if (countOfRTS > 0)
        {
            short rtsSize = 1;
            if (segmentNr > 256)
            {
                rtsSize = 2;
                if (segmentNr > 65536)
                {
                    rtsSize = 4;
                }
            }

            rtSegments = new SegmentHeader[countOfRTS];

            printDebugMessage("|-Length of RT segments list: " + rtSegments.length);

            for (int i = 0; i < countOfRTS; i++)
            {
                rtsNumbers[i] = (int) (subInputStream.readBits(rtsSize << 3) & 0xffffffff);
            }
        }

        return rtsNumbers;
    }

    /**
     * 7.2.6 Segment page association
     * 
     * @param document
     * @param subInputStream
     * @param countOfRTS
     * @param rtsNumbers
     * @throws IOException
     */
    private void readSegmentPageAssociation(JBIG2Document document, ImageInputStream subInputStream,
            int countOfRTS, int[] rtsNumbers) throws IOException
    {
        if (pageAssociationFieldSize == 0)
        {
            // Short format
            pageAssociation = (short) (subInputStream.readBits(8) & 0xff);
        }
        else
        {
            // Long format
            pageAssociation = (int) (subInputStream.readBits(32) & 0xffffffff);
        }

        if (countOfRTS > 0)
        {
            final JBIG2Page page = document.getPage(pageAssociation);
            for (int i = 0; i < countOfRTS; i++)
            {
                rtSegments[i] = (null != page ? page.getSegment(rtsNumbers[i])
                        : document.getGlobalSegment(rtsNumbers[i]));
            }
        }
    }

    /**
     * 7.2.7 Segment data length
     * <p>
     * Contains the length of the data part in bytes.
     * 
     * @param subInputStream
     * @throws IOException
     */
    private void readSegmentDataLength(ImageInputStream subInputStream) throws IOException
    {
        segmentDataLength = (subInputStream.readBits(32) & 0xffffffff);
        printDebugMessage("|-Data length: " + segmentDataLength);
    }

    /**
     * Sets the offset only if organization type is SEQUENTIAL. If random, data starts after segment headers and can be
     * determined when all segment headers are parsed and allocated.
     * 
     * @param subInputStream
     * @param organisationType
     * @throws IOException
     */
    private void readDataStartOffset(ImageInputStream subInputStream, int organisationType)
            throws IOException
    {
        if (organisationType == JBIG2Document.SEQUENTIAL)
        {
            printDebugMessage("|-Organization is sequential.");
            segmentDataStartOffset = subInputStream.getStreamPosition();
        }
    }

    private void readSegmentHeaderLength(ImageInputStream subInputStream, long offset)
            throws IOException
    {
        segmentHeaderLength = subInputStream.getStreamPosition() - offset;
        printDebugMessage("|-Segment header length: " + segmentHeaderLength);
    }

    private void printDebugMessage(String message)
    {
        log.debug(message);
    }

    public int getSegmentNr()
    {
        return segmentNr;
    }

    public int getSegmentType()
    {
        return segmentType;
    }

    public long getSegmentHeaderLength()
    {
        return segmentHeaderLength;
    }

    public long getSegmentDataLength()
    {
        return segmentDataLength;
    }

    public long getSegmentDataStartOffset()
    {
        return segmentDataStartOffset;
    }

    public void setSegmentDataStartOffset(long segmentDataStartOffset)
    {
        this.segmentDataStartOffset = segmentDataStartOffset;
    }

    public SegmentHeader[] getRtSegments()
    {
        return rtSegments;
    }

    public int getPageAssociation()
    {
        return pageAssociation;
    }

    public short getRetainFlag()
    {
        return retainFlag;
    }

    /**
     * Creates and returns a new {@link SubInputStream} that provides the data part of this segment. It is a clipped
     * view of the source input stream.
     * 
     * @return The {@link SubInputStream} that represents the data part of the segment.
     */
    public SubInputStream getDataInputStream()
    {
        return new SubInputStream(subInputStream, segmentDataStartOffset, segmentDataLength);
    }

    /**
     * Retrieves the segments' data part.
     * 
     * @return Retrieved {@link SegmentData} instance.
     */
    public SegmentData getSegmentData()
    {
        SegmentData segmentDataPart = null;

        if (null != segmentData)
        {
            segmentDataPart = segmentData.get();
        }

        if (null == segmentDataPart)
        {
            try
            {

                Class<? extends SegmentData> segmentClass = SEGMENT_TYPE_MAP.get(segmentType);

                if (null == segmentClass)
                {
                    throw new IllegalArgumentException("No segment class for type " + segmentType);
                }

                segmentDataPart = segmentClass.newInstance();
                segmentDataPart.init(this, getDataInputStream());

                segmentData = new SoftReference<SegmentData>(segmentDataPart);

            }
            catch (Exception e)
            {
                throw new RuntimeException("Can't instantiate segment class", e);
            }
        }

        return segmentDataPart;
    }

    public void cleanSegmentData()
    {
        if (segmentData != null)
        {
            segmentData = null;
        }
    }

    public String toString()
    {
        StringBuilder stringBuilder = new StringBuilder();

        if (rtSegments != null)
        {
            for (SegmentHeader s : rtSegments)
            {
                stringBuilder.append(s.segmentNr + " ");
            }
        }
        else
        {
            stringBuilder.append("none");
        }

        return "\n#SegmentNr: " + segmentNr //
                + "\n SegmentType: " + segmentType //
                + "\n PageAssociation: " + pageAssociation //
                + "\n Referred-to segments: " + stringBuilder.toString() //
                + "\n"; //
    }
}
