/*
 * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package com.sun.media.sound;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.RandomAccessFile;

/**
 * Resource Interchange File Format (RIFF) stream encoder.
 *
 * @author Karl Helgason
 */
public class RIFFWriter extends OutputStream {

    private interface RandomAccessWriter {

        public void seek(long chunksizepointer) throws IOException;

        public long getPointer() throws IOException;

        public void close() throws IOException;

        public void write(int b) throws IOException;

        public void write(byte[] b, int off, int len) throws IOException;

        public void write(byte[] bytes) throws IOException;

        public long length() throws IOException;

        public void setLength(long i) throws IOException;
    }

    private static class RandomAccessFileWriter implements RandomAccessWriter {

        RandomAccessFile raf;

        public RandomAccessFileWriter(File file) throws FileNotFoundException {
            this.raf = new RandomAccessFile(file, "rw");
        }

        public RandomAccessFileWriter(String name) throws FileNotFoundException {
            this.raf = new RandomAccessFile(name, "rw");
        }

        public void seek(long chunksizepointer) throws IOException {
            raf.seek(chunksizepointer);
        }

        public long getPointer() throws IOException {
            return raf.getFilePointer();
        }

        public void close() throws IOException {
            raf.close();
        }

        public void write(int b) throws IOException {
            raf.write(b);
        }

        public void write(byte[] b, int off, int len) throws IOException {
            raf.write(b, off, len);
        }

        public void write(byte[] bytes) throws IOException {
            raf.write(bytes);
        }

        public long length() throws IOException {
            return raf.length();
        }

        public void setLength(long i) throws IOException {
            raf.setLength(i);
        }
    }

    private static class RandomAccessByteWriter implements RandomAccessWriter {

        byte[] buff = new byte[32];
        int length = 0;
        int pos = 0;
        byte[] s;
        OutputStream stream;

        public RandomAccessByteWriter(OutputStream stream) {
            this.stream = stream;
        }

        public void seek(long chunksizepointer) throws IOException {
            pos = (int) chunksizepointer;
        }

        public long getPointer() throws IOException {
            return pos;
        }

        public void close() throws IOException {
            stream.write(buff, 0, length);
            stream.close();
        }

        public void write(int b) throws IOException {
            if (s == null)
                s = new byte[1];
            s[0] = (byte)b;
            write(s, 0, 1);
        }

        public void write(byte[] b, int off, int len) throws IOException {
            int newsize = pos + len;
            if (newsize > length)
                setLength(newsize);
            int end = off + len;
            for (int i = off; i < end; i++) {
                buff[pos++] = b[i];
            }
        }

        public void write(byte[] bytes) throws IOException {
            write(bytes, 0, bytes.length);
        }

        public long length() throws IOException {
            return length;
        }

        public void setLength(long i) throws IOException {
            length = (int) i;
            if (length > buff.length) {
                int newlen = Math.max(buff.length << 1, length);
                byte[] newbuff = new byte[newlen];
                System.arraycopy(buff, 0, newbuff, 0, buff.length);
                buff = newbuff;
            }
        }
    }
    private int chunktype = 0; // 0=RIFF, 1=LIST; 2=CHUNK
    private RandomAccessWriter raf;
    private long chunksizepointer;
    private long startpointer;
    private RIFFWriter childchunk = null;
    private boolean open = true;
    private boolean writeoverride = false;

    public RIFFWriter(String name, String format) throws IOException {
        this(new RandomAccessFileWriter(name), format, 0);
    }

    public RIFFWriter(File file, String format) throws IOException {
        this(new RandomAccessFileWriter(file), format, 0);
    }

    public RIFFWriter(OutputStream stream, String format) throws IOException {
        this(new RandomAccessByteWriter(stream), format, 0);
    }

    private RIFFWriter(RandomAccessWriter raf, String format, int chunktype)
            throws IOException {
        if (chunktype == 0)
            if (raf.length() != 0)
                raf.setLength(0);
        this.raf = raf;
        if (raf.getPointer() % 2 != 0)
            raf.write(0);

        if (chunktype == 0)
            raf.write("RIFF".getBytes("ascii"));
        else if (chunktype == 1)
            raf.write("LIST".getBytes("ascii"));
        else
            raf.write((format + "    ").substring(0, 4).getBytes("ascii"));

        chunksizepointer = raf.getPointer();
        this.chunktype = 2;
        writeUnsignedInt(0);
        this.chunktype = chunktype;
        startpointer = raf.getPointer();
        if (chunktype != 2)
            raf.write((format + "    ").substring(0, 4).getBytes("ascii"));

    }

    public void seek(long pos) throws IOException {
        raf.seek(pos);
    }

    public long getFilePointer() throws IOException {
        return raf.getPointer();
    }

    public void setWriteOverride(boolean writeoverride) {
        this.writeoverride = writeoverride;
    }

    public boolean getWriteOverride() {
        return writeoverride;
    }

    public void close() throws IOException {
        if (!open)
            return;
        if (childchunk != null) {
            childchunk.close();
            childchunk = null;
        }

        int bakchunktype = chunktype;
        long fpointer = raf.getPointer();
        raf.seek(chunksizepointer);
        chunktype = 2;
        writeUnsignedInt(fpointer - startpointer);

        if (bakchunktype == 0)
            raf.close();
        else
            raf.seek(fpointer);
        open = false;
        raf = null;
    }

    public void write(int b) throws IOException {
        if (!writeoverride) {
            if (chunktype != 2) {
                throw new IllegalArgumentException(
                        "Only chunks can write bytes!");
            }
            if (childchunk != null) {
                childchunk.close();
                childchunk = null;
            }
        }
        raf.write(b);
    }

    public void write(byte b[], int off, int len) throws IOException {
        if (!writeoverride) {
            if (chunktype != 2) {
                throw new IllegalArgumentException(
                        "Only chunks can write bytes!");
            }
            if (childchunk != null) {
                childchunk.close();
                childchunk = null;
            }
        }
        raf.write(b, off, len);
    }

    public RIFFWriter writeList(String format) throws IOException {
        if (chunktype == 2) {
            throw new IllegalArgumentException(
                    "Only LIST and RIFF can write lists!");
        }
        if (childchunk != null) {
            childchunk.close();
            childchunk = null;
        }
        childchunk = new RIFFWriter(this.raf, format, 1);
        return childchunk;
    }

    public RIFFWriter writeChunk(String format) throws IOException {
        if (chunktype == 2) {
            throw new IllegalArgumentException(
                    "Only LIST and RIFF can write chunks!");
        }
        if (childchunk != null) {
            childchunk.close();
            childchunk = null;
        }
        childchunk = new RIFFWriter(this.raf, format, 2);
        return childchunk;
    }

    // Write ASCII chars to stream
    public void writeString(String string) throws IOException {
        byte[] buff = string.getBytes();
        write(buff);
    }

    // Write ASCII chars to stream
    public void writeString(String string, int len) throws IOException {
        byte[] buff = string.getBytes();
        if (buff.length > len)
            write(buff, 0, len);
        else {
            write(buff);
            for (int i = buff.length; i < len; i++)
                write(0);
        }
    }

    // Write 8 bit signed integer to stream
    public void writeByte(int b) throws IOException {
        write(b);
    }

    // Write 16 bit signed integer to stream
    public void writeShort(short b) throws IOException {
        write((b >>> 0) & 0xFF);
        write((b >>> 8) & 0xFF);
    }

    // Write 32 bit signed integer to stream
    public void writeInt(int b) throws IOException {
        write((b >>> 0) & 0xFF);
        write((b >>> 8) & 0xFF);
        write((b >>> 16) & 0xFF);
        write((b >>> 24) & 0xFF);
    }

    // Write 64 bit signed integer to stream
    public void writeLong(long b) throws IOException {
        write((int) (b >>> 0) & 0xFF);
        write((int) (b >>> 8) & 0xFF);
        write((int) (b >>> 16) & 0xFF);
        write((int) (b >>> 24) & 0xFF);
        write((int) (b >>> 32) & 0xFF);
        write((int) (b >>> 40) & 0xFF);
        write((int) (b >>> 48) & 0xFF);
        write((int) (b >>> 56) & 0xFF);
    }

    // Write 8 bit unsigned integer to stream
    public void writeUnsignedByte(int b) throws IOException {
        writeByte((byte) b);
    }

    // Write 16 bit unsigned integer to stream
    public void writeUnsignedShort(int b) throws IOException {
        writeShort((short) b);
    }

    // Write 32 bit unsigned integer to stream
    public void writeUnsignedInt(long b) throws IOException {
        writeInt((int) b);
    }
}
