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

import java.io.IOException;
import java.io.OutputStream;

import org.apache.commons.sanselan.common.BinaryConstants;

public class MyBitOutputStream extends OutputStream implements BinaryConstants
{
    private final OutputStream os;
    private final int byteOrder;

    public MyBitOutputStream(OutputStream os, int byteOrder)
    {
        this.byteOrder = byteOrder;
        this.os = os;
    }

    @Override
    public void write(int value) throws IOException
    {
        writeBits(value, 8);
    }

    private int bitsInCache = 0;
    private int bitCache = 0;

    // TODO: in and out streams CANNOT accurately read/write 32bits at a time,
    // as int will overflow.  should have used a long
    public void writeBits(int value, int SampleBits) throws IOException
    {
        int sampleMask = (1 << SampleBits) - 1;
        value &= sampleMask;

        if (byteOrder == BYTE_ORDER_NETWORK) // MSB, so add to right
        {
            bitCache = (bitCache << SampleBits) | value;
        }
        else if (byteOrder == BYTE_ORDER_INTEL) // LSB, so add to left
        {
            bitCache = bitCache | (value << bitsInCache);
        }
        else
            throw new IOException("Unknown byte order: " + byteOrder);
        bitsInCache += SampleBits;

        while (bitsInCache >= 8)
        {
            if (byteOrder == BYTE_ORDER_NETWORK) // MSB, so write from left
            {
                int b = 0xff & (bitCache >> (bitsInCache - 8));
                actualWrite(b);

                bitsInCache -= 8;
            }
            else if (byteOrder == BYTE_ORDER_INTEL) // LSB, so write from right
            {
                int b = 0xff & bitCache;
                actualWrite(b);

                bitCache >>= 8;
                bitsInCache -= 8;
            }
            int remainderMask = (1 << bitsInCache) - 1; // unneccesary
            bitCache &= remainderMask; // unneccesary
        }

    }

    private int bytesWritten = 0;

    private void actualWrite(int value) throws IOException
    {
        os.write(value);
        bytesWritten++;
    }

    public void flushCache() throws IOException
    {
        if (bitsInCache > 0)
        {
            int bitMask = (1 << bitsInCache) - 1;
            int b = bitMask & bitCache;

            if (byteOrder == BYTE_ORDER_NETWORK) // MSB, so write from left
            {
                b <<= 8 - bitsInCache; // left align fragment.
                os.write(b);
            }
            else if (byteOrder == BYTE_ORDER_INTEL) // LSB, so write from right
            {
                os.write(b);
            }
        }

        bitsInCache = 0;
        bitCache = 0;
    }

    public int getBytesWritten()
    {
        return bytesWritten + ((bitsInCache > 0) ? 1 : 0);
    }

}