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

import org.apache.commons.sanselan.ImageWriteException;

public class BinaryOutputStream extends OutputStream implements BinaryConstants
{
    protected boolean debug = false;
    private int count = 0;

    public final void setDebug(boolean b)
    {
        debug = b;
    }

    public final boolean getDebug()
    {
        return debug;
    }

    private final OutputStream os;

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

    public BinaryOutputStream(OutputStream os)
    {
        this.os = os;
    }

    // default byte order for Java, many file formats.
    private int byteOrder = BYTE_ORDER_NETWORK;

    protected void setByteOrder(int a, int b) throws ImageWriteException
    {
        if (a != b)
            throw new ImageWriteException("Byte Order bytes don't match (" + a
                    + ", " + b + ").");

        if (a == BYTE_ORDER_MOTOROLA)
            byteOrder = a;
        else if (a == BYTE_ORDER_INTEL)
            byteOrder = a;
        else
            throw new ImageWriteException("Unknown Byte Order hint: " + a);
    }

    protected void setByteOrder(int byteOrder)
    {
        this.byteOrder = byteOrder;
    }

    public int getByteOrder()
    {
        return byteOrder;
    }

    @Override
    public void write(int i) throws IOException
    {
        os.write(i);
        count++;
    }

    public int getByteCount()
    {
        return count;
    }

    public final void write4Bytes(int value) throws IOException
    {
        writeNBytes(value, 4);
    }

    public final void write3Bytes(int value) throws IOException
    {
        writeNBytes(value, 3);
    }

    public final void write2Bytes(int value) throws IOException
    {
        writeNBytes(value, 2);
    }

    public final void write4ByteInteger(int value) throws IOException
    {
        if (byteOrder == BYTE_ORDER_MOTOROLA)
        {
            write(0xff & (value >> 24));
            write(0xff & (value >> 16));
            write(0xff & (value >> 8));
            write(0xff & value);
        } else
        {
            write(0xff & value);
            write(0xff & (value >> 8));
            write(0xff & (value >> 16));
            write(0xff & (value >> 24));
        }
    }

    public final void write2ByteInteger(int value) throws IOException
    {
        if (byteOrder == BYTE_ORDER_MOTOROLA)
        {
            write(0xff & (value >> 8));
            write(0xff & value);
        } else
        {
            write(0xff & value);
            write(0xff & (value >> 8));
        }
    }

    public final void writeByteArray(byte bytes[]) throws IOException
    {
        os.write(bytes, 0, bytes.length);
        count += bytes.length;
    }

    private byte[] convertValueToByteArray(int value, int n)
    {
        byte result[] = new byte[n];

        if (byteOrder == BYTE_ORDER_MOTOROLA)
        {
            for (int i = 0; i < n; i++)
            {
                int b = 0xff & (value >> (8 * (n - i - 1)));
                result[i] = (byte) b;
            }
        } else
        {
            for (int i = 0; i < n; i++)
            {
                int b = 0xff & (value >> (8 * i));
                result[i] = (byte) b;
            }
        }

        return result;
    }

    private final void writeNBytes(int value, int n)
            throws IOException
    {
        write(convertValueToByteArray(value, n));
    }

}