/*
 * 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;

import java.io.IOException;
import java.io.InputStream;

public class BitInputStream extends InputStream implements BinaryConstants
{
    
    private final InputStream is;
    private final int byteOrder;

    public BitInputStream(InputStream is, int byteOrder)
    {
        this.is = is;
        this.byteOrder = byteOrder;
        //            super(is);
    }

    @Override
    public int read() throws IOException
    {
        if (cacheBitsRemaining > 0)
            throw new IOException("BitInputStream: incomplete bit read");
        return is.read();
    }

    private int cache;
    private int cacheBitsRemaining = 0;
    private long bytes_read = 0;

    public final int readBits(int count) throws IOException
    {
        if (count < 8)
        {
            if (cacheBitsRemaining == 0)
            {
                // fill cache
                cache = is.read();
                cacheBitsRemaining = 8;
                bytes_read++;
            }
            if (count > cacheBitsRemaining)
                throw new IOException(
                        "BitInputStream: can't read bit fields across bytes");

            //                int bits_to_shift = cache_bits_remaining - count;
            cacheBitsRemaining -= count;
            int bits = cache >> cacheBitsRemaining;

            switch (count)
            {
                case 1 :
                    return bits & 1;
                case 2 :
                    return bits & 3;
                case 3 :
                    return bits & 7;
                case 4 :
                    return bits & 15;
                case 5 :
                    return bits & 31;
                case 6 :
                    return bits & 63;
                case 7 :
                    return bits & 127;
            }

        }
        if (cacheBitsRemaining > 0)
            throw new IOException("BitInputStream: incomplete bit read");

        if (count == 8)
        {
            bytes_read++;
            return is.read();
        }
        
        /**
         * Taking default order of the Tiff to be 
         * Little Endian and reversing the bytes in the end
         * if its Big Endian.This is done because majority (may be all)
         * of the files will be of Little Endian.
         */
        if(byteOrder == BYTE_ORDER_BIG_ENDIAN) {
            if (count == 16)
            {
                bytes_read += 2;
                return (is.read() << 8) | (is.read() << 0);
            }

            if (count == 24)
            {
                bytes_read += 3;
                return (is.read() << 16) | (is.read() << 8) | (is.read() << 0);
            }

            if (count == 32)
            {
                bytes_read += 4;
                return (is.read() << 24) | (is.read() << 16) | (is.read() << 8)
                        | (is.read() << 0);
            }
        } 
        else 
        {
            if(count == 16) 
            {
                bytes_read +=2;
                return ((is.read() << 0) | (is.read() << 8));
            }
            
            if(count == 24)
            {
                bytes_read += 3;
                return ((is.read() << 0) | (is.read() << 8) | (is.read() << 16));
            }
            
            if(count == 32) 
            {
                bytes_read += 4;
                return ((is.read() << 0) | (is.read() << 8) | (is.read() << 16) | (is.read() << 24));
            }
         }

        throw new IOException("BitInputStream: unknown error");
    }

    public void flushCache()
    {
        cacheBitsRemaining = 0;
    }

    public long getBytesRead()
    {
        return bytes_read;
    }
}