/*
 * 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.util.HashMap;
import java.util.Map;

public class MyLzwCompressor
{

    // private static final int MAX_TABLE_SIZE = 1 << 12;

    private int codeSize;
    private final int initialCodeSize;
    private int codes = -1;

    private final int byteOrder;
    private final boolean earlyLimit;
    private final int clearCode;
    private final int eoiCode;
    private final Listener listener;

    public MyLzwCompressor(int initialCodeSize, int byteOrder,
            boolean earlyLimit)
    {
        this(initialCodeSize, byteOrder, earlyLimit, null);
    }

    public MyLzwCompressor(int initialCodeSize, int byteOrder,
            boolean earlyLimit, Listener listener)
    {
        this.listener = listener;
        this.byteOrder = byteOrder;
        this.earlyLimit = earlyLimit;

        this.initialCodeSize = initialCodeSize;

        clearCode = 1 << initialCodeSize;
        eoiCode = clearCode + 1;

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

        InitializeStringTable();
    }

    private final Map<Object, Integer> map = new HashMap<Object, Integer>();

    private final void InitializeStringTable()
    {
        codeSize = initialCodeSize;

        int intial_entries_count = (1 << codeSize) + 2;

        map.clear();
        for (codes = 0; codes < intial_entries_count; codes++)
        {
            if ((codes != clearCode) && (codes != eoiCode))
            {
                Object key = arrayToKey((byte) codes);

                map.put(key, codes);
            }
        }
    }

    private final void clearTable()
    {
        InitializeStringTable();
        incrementCodeSize();
    }

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

    private final Object arrayToKey(byte b)
    {
        return arrayToKey(new byte[] { b, }, 0, 1);
    }

    private final static class ByteArray
    {
        private final byte bytes[];
        private final int start;
        private final int length;
        private final int hash;

        public ByteArray(byte bytes[])
        {
            this(bytes, 0, bytes.length);
        }

        public ByteArray(byte bytes[], int start, int length)
        {
            this.bytes = bytes;
            this.start = start;
            this.length = length;

            int tempHash = length;

            for (int i = 0; i < length; i++)
            {
                int b = 0xff & bytes[i + start];
                tempHash = tempHash + (tempHash << 8) ^ b ^ i;
            }

            hash = tempHash;
        }

        @Override
        public final int hashCode()
        {
            return hash;
        }

        @Override
        public final boolean equals(Object o)
        {
            if (o instanceof ByteArray) {
                ByteArray other = (ByteArray) o;
                if (other.hash != hash)
                    return false;
                if (other.length != length)
                    return false;

                for (int i = 0; i < length; i++)
                {
                    if (other.bytes[i + other.start] != bytes[i + start])
                        return false;
                }

                return true;
            }
            return false;
        }
    }

    private final Object arrayToKey(byte bytes[], int start, int length)
    {
        return new ByteArray(bytes, start, length);
    }

    private final void writeDataCode(MyBitOutputStream bos, int code)
            throws IOException
    {
        if (null != listener)
            listener.dataCode(code);
        writeCode(bos, code);
    }


    private final void writeClearCode(MyBitOutputStream bos) throws IOException
    {
        if (null != listener)
            listener.dataCode(clearCode);
        writeCode(bos, clearCode);
    }

    private final void writeEoiCode(MyBitOutputStream bos) throws IOException
    {
        if (null != listener)
            listener.eoiCode(eoiCode);
        writeCode(bos, eoiCode);
    }

    private final void writeCode(MyBitOutputStream bos, int code)
            throws IOException
    {
        bos.writeBits(code, codeSize);
    }

    private final boolean isInTable(byte bytes[], int start, int length)
    {
        Object key = arrayToKey(bytes, start, length);

        return map.containsKey(key);
    }

    private final int codeFromString(byte bytes[], int start, int length)
            throws IOException
    {
        Object key = arrayToKey(bytes, start, length);
        Object o = map.get(key);
        if (o == null)
            throw new IOException("CodeFromString");
        return ((Integer) o).intValue();
    }

    private final boolean addTableEntry(MyBitOutputStream bos, byte bytes[],
            int start, int length) throws IOException
    {
        Object key = arrayToKey(bytes, start, length);
        return addTableEntry(bos, key);
    }

    private final boolean addTableEntry(MyBitOutputStream bos, Object key)
            throws IOException
    {
        boolean cleared = false;

        {
            int limit = (1 << codeSize);
            if (earlyLimit)
                limit--;

            if (codes == limit)
            {
                if (codeSize < 12)
                    incrementCodeSize();
                else
                {
                    writeClearCode(bos);
                    clearTable();
                    cleared = true;
                }
            }
        }

        if (!cleared)
        {
            map.put(key, codes);
            codes++;
        }

        return cleared;
    }

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

        public void eoiCode(int code);

        public void clearCode(int code);

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

    public byte[] compress(byte bytes[]) throws IOException
    {
        ByteArrayOutputStream baos = new ByteArrayOutputStream(bytes.length);
        MyBitOutputStream bos = new MyBitOutputStream(baos, byteOrder);

        InitializeStringTable();
        clearTable();
        writeClearCode(bos);
        boolean cleared = false;

        int w_start = 0;
        int w_length = 0;

        for (int i = 0; i < bytes.length; i++)
        {
            if (isInTable(bytes, w_start, w_length + 1))
            {
                w_length++;

                cleared = false;
            } else
            {
                int code = codeFromString(bytes, w_start, w_length);
                writeDataCode(bos, code);
                cleared = addTableEntry(bos, bytes, w_start, w_length + 1);

                w_start = i;
                w_length = 1;
            }
        } /* end of for loop */

        int code = codeFromString(bytes, w_start, w_length);
        writeDataCode(bos, code);

        writeEoiCode(bos);

        bos.flushCache();

        return baos.toByteArray();
    }
}