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

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public final class MyLzwDecompressor
{
    private static final int MAX_TABLE_SIZE = 1 << 12;

    private final byte[][] table;
    private int codeSize;
    private final int initialCodeSize;
    private int codes = -1;

    private final int byteOrder;

    private final Listener listener;

    public static interface Listener
    {
        public void code(int code);

        public void init(int clearCode, int eoiCode);
    }

    public MyLzwDecompressor(int initialCodeSize, int byteOrder)
    {
        this(initialCodeSize, byteOrder, null);
    }

    public MyLzwDecompressor(int initialCodeSize, int byteOrder,
            Listener listener)
    {
        this.listener = listener;
        this.byteOrder = byteOrder;

        this.initialCodeSize = initialCodeSize;

        table = new byte[MAX_TABLE_SIZE][];
        clearCode = 1 << initialCodeSize;
        eoiCode = clearCode + 1;

        if (null != listener)
            listener.init(clearCode, eoiCode);

        InitializeTable();
    }

    private final void InitializeTable()
    {
        codeSize = initialCodeSize;

        int intial_entries_count = 1 << codeSize + 2;

        for (int i = 0; i < intial_entries_count; i++)
            table[i] = new byte[] { (byte) i, };
    }

    private final void clearTable()
    {
        codes = (1 << initialCodeSize) + 2;
        codeSize = initialCodeSize;
        incrementCodeSize();
    }

    private final int clearCode;
    private final int eoiCode;

    private final int getNextCode(MyBitInputStream is) throws IOException
    {
        int code = is.readBits(codeSize);

        if (null != listener)
            listener.code(code);
        return code;
    }

    private final byte[] stringFromCode(int code) throws IOException
    {
        if ((code >= codes) || (code < 0))
            throw new IOException("Bad Code: " + code + " codes: " + codes
                    + " code_size: " + codeSize + ", table: " + table.length);

        return table[code];
    }

    private final boolean isInTable(int Code)
    {
        return Code < codes;
    }

    private final byte firstChar(byte bytes[])
    {
        return bytes[0];
    }

    private final void addStringToTable(byte bytes[]) throws IOException
    {
        if (codes < (1 << codeSize))
        {
            table[codes] = bytes;
            codes++;
        } else
            throw new IOException("AddStringToTable: codes: " + codes
                    + " code_size: " + codeSize);

        checkCodeSize();
    }

    private final byte[] appendBytes(byte bytes[], byte b)
    {
        byte result[] = new byte[bytes.length + 1];

        System.arraycopy(bytes, 0, result, 0, bytes.length);
        result[result.length - 1] = b;
        return result;
    }

    private int written = 0;

    private final void writeToResult(OutputStream os, byte bytes[])
            throws IOException
    {
        os.write(bytes);
        written += bytes.length;
    }

    private boolean tiffLZWMode = false;

    public void setTiffLZWMode()
    {
        tiffLZWMode = true;
    }

    public byte[] decompress(InputStream is, int expectedLength)
            throws IOException
    {
        int code, oldCode = -1;
        MyBitInputStream mbis = new MyBitInputStream(is, byteOrder);
        if (tiffLZWMode)
            mbis.setTiffLZWMode();

        ByteArrayOutputStream baos = new ByteArrayOutputStream(expectedLength);

        clearTable();

        while ((code = getNextCode(mbis)) != eoiCode)
        {
            if (code == clearCode)
            {
                clearTable();

                if (written >= expectedLength)
                    break;
                code = getNextCode(mbis);

                if (code == eoiCode)
                {
                    break;
                }
                writeToResult(baos, stringFromCode(code));

                oldCode = code;
            } // end of ClearCode case
            else
            {
                if (isInTable(code))
                {
                    writeToResult(baos, stringFromCode(code));

                    addStringToTable(appendBytes(stringFromCode(oldCode),
                            firstChar(stringFromCode(code))));
                    oldCode = code;
                } else
                {
                    byte OutString[] = appendBytes(stringFromCode(oldCode),
                            firstChar(stringFromCode(oldCode)));
                    writeToResult(baos, OutString);
                    addStringToTable(OutString);
                    oldCode = code;
                }
            } // end of not-ClearCode case

            if (written >= expectedLength)
                break;
        } // end of while loop

        byte result[] = baos.toByteArray();

        return result;
    }

    private final void checkCodeSize() // throws IOException
    {
        int limit = (1 << codeSize);
        if (tiffLZWMode)
            limit--;

        if (codes == limit)
            incrementCodeSize();
    }

    private final void incrementCodeSize() // throws IOException
    {
        if (codeSize != 12)
            codeSize++;
    }
}