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

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;
    }
}