/*
 * Copyright 1999-2007 Sun Microsystems, Inc.  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.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package com.sun.media.sound;

import java.util.Vector;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.lang.IllegalArgumentException;

import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.RandomAccessFile;
import java.io.SequenceInputStream;

import javax.sound.sampled.AudioFileFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioSystem;


/**
 * AU file writer.
 *
 * @author Jan Borgersen
 */
public class AuFileWriter extends SunFileWriter {

    //$$fb value for length field if length is not known
    public final static int UNKNOWN_SIZE=-1;

    /**
     * AU type
     */
    private static final AudioFileFormat.Type auTypes[] = {
        AudioFileFormat.Type.AU
    };


    /**
     * Constructs a new AuFileWriter object.
     */
    public AuFileWriter() {
        super(auTypes);
    }



    public AudioFileFormat.Type[] getAudioFileTypes(AudioInputStream stream) {

        AudioFileFormat.Type[] filetypes = new AudioFileFormat.Type[types.length];
        System.arraycopy(types, 0, filetypes, 0, types.length);

        // make sure we can write this stream
        AudioFormat format = stream.getFormat();
        AudioFormat.Encoding encoding = format.getEncoding();

        if( (AudioFormat.Encoding.ALAW.equals(encoding)) ||
            (AudioFormat.Encoding.ULAW.equals(encoding)) ||
            (AudioFormat.Encoding.PCM_SIGNED.equals(encoding)) ||
            (AudioFormat.Encoding.PCM_UNSIGNED.equals(encoding)) ) {

            return filetypes;
        }

        return new AudioFileFormat.Type[0];
    }


    public int write(AudioInputStream stream, AudioFileFormat.Type fileType, OutputStream out) throws IOException {

        // we must know the total data length to calculate the file length
        //$$fb 2001-07-13: fix for bug 4351296: do not throw an exception
        //if( stream.getFrameLength() == AudioSystem.NOT_SPECIFIED ) {
        //      throw new IOException("stream length not specified");
        //}

        // throws IllegalArgumentException if not supported
        AuFileFormat auFileFormat = (AuFileFormat)getAudioFileFormat(fileType, stream);

        int bytesWritten = writeAuFile(stream, auFileFormat, out);
        return bytesWritten;
    }



    public int write(AudioInputStream stream, AudioFileFormat.Type fileType, File out) throws IOException {

        // throws IllegalArgumentException if not supported
        AuFileFormat auFileFormat = (AuFileFormat)getAudioFileFormat(fileType, stream);

        // first write the file without worrying about length fields
        FileOutputStream fos = new FileOutputStream( out );     // throws IOException
        BufferedOutputStream bos = new BufferedOutputStream( fos, bisBufferSize );
        int bytesWritten = writeAuFile(stream, auFileFormat, bos );
        bos.close();

        // now, if length fields were not specified, calculate them,
        // open as a random access file, write the appropriate fields,
        // close again....
        if( auFileFormat.getByteLength()== AudioSystem.NOT_SPECIFIED ) {

            // $$kk: 10.22.99: jan: please either implement this or throw an exception!
            // $$fb: 2001-07-13: done. Fixes Bug 4479981
            RandomAccessFile raf=new RandomAccessFile(out, "rw");
            if (raf.length()<=0x7FFFFFFFl) {
                                // skip AU magic and data offset field
                raf.skipBytes(8);
                raf.writeInt(bytesWritten-AuFileFormat.AU_HEADERSIZE);
                                // that's all
            }
            raf.close();
        }

        return bytesWritten;
    }


    // -------------------------------------------------------------

    /**
     * Returns the AudioFileFormat describing the file that will be written from this AudioInputStream.
     * Throws IllegalArgumentException if not supported.
     */
    private AudioFileFormat getAudioFileFormat(AudioFileFormat.Type type, AudioInputStream stream) {

        AudioFormat format = null;
        AuFileFormat fileFormat = null;
        AudioFormat.Encoding encoding = AudioFormat.Encoding.PCM_SIGNED;

        AudioFormat streamFormat = stream.getFormat();
        AudioFormat.Encoding streamEncoding = streamFormat.getEncoding();


        float sampleRate;
        int sampleSizeInBits;
        int channels;
        int frameSize;
        float frameRate;
        int fileSize;

        if( !types[0].equals(type) ) {
            throw new IllegalArgumentException("File type " + type + " not supported.");
        }

        if( (AudioFormat.Encoding.ALAW.equals(streamEncoding)) ||
            (AudioFormat.Encoding.ULAW.equals(streamEncoding)) ) {

            encoding = streamEncoding;
            sampleSizeInBits = streamFormat.getSampleSizeInBits();

        } else if ( streamFormat.getSampleSizeInBits()==8 ) {

            encoding = AudioFormat.Encoding.PCM_SIGNED;
            sampleSizeInBits=8;

        } else {

            encoding = AudioFormat.Encoding.PCM_SIGNED;
            sampleSizeInBits=streamFormat.getSampleSizeInBits();
        }


        format = new AudioFormat( encoding,
                                  streamFormat.getSampleRate(),
                                  sampleSizeInBits,
                                  streamFormat.getChannels(),
                                  streamFormat.getFrameSize(),
                                  streamFormat.getFrameRate(),
                                  true);        // AU is always big endian


        if( stream.getFrameLength()!=AudioSystem.NOT_SPECIFIED ) {
            fileSize = (int)stream.getFrameLength()*streamFormat.getFrameSize() + AuFileFormat.AU_HEADERSIZE;
        } else {
            fileSize = AudioSystem.NOT_SPECIFIED;
        }

        fileFormat = new AuFileFormat( AudioFileFormat.Type.AU,
                                       fileSize,
                                       format,
                                       (int)stream.getFrameLength() );

        return fileFormat;
    }


    private InputStream getFileStream(AuFileFormat auFileFormat, InputStream audioStream) throws IOException {

        // private method ... assumes auFileFormat is a supported file type

        AudioFormat format            = auFileFormat.getFormat();

        int magic          = AuFileFormat.AU_SUN_MAGIC;
        int headerSize     = AuFileFormat.AU_HEADERSIZE;
        long dataSize       = auFileFormat.getFrameLength();
        //$$fb fix for Bug 4351296
        //int dataSizeInBytes = dataSize * format.getFrameSize();
        long dataSizeInBytes = (dataSize==AudioSystem.NOT_SPECIFIED)?UNKNOWN_SIZE:dataSize * format.getFrameSize();
        if (dataSizeInBytes>0x7FFFFFFFl) {
            dataSizeInBytes=UNKNOWN_SIZE;
        }
        int encoding_local = auFileFormat.getAuType();
        int sampleRate     = (int)format.getSampleRate();
        int channels       = format.getChannels();
        //$$fb below is the fix for 4297100.
        //boolean bigendian      = format.isBigEndian();
        boolean bigendian      = true;                  // force bigendian

        byte header[] = null;
        ByteArrayInputStream headerStream = null;
        ByteArrayOutputStream baos = null;
        DataOutputStream dos = null;
        SequenceInputStream auStream = null;

        AudioFormat audioStreamFormat = null;
        AudioFormat.Encoding encoding = null;
        InputStream codedAudioStream = audioStream;

        // if we need to do any format conversion, do it here.

        codedAudioStream = audioStream;

        if( audioStream instanceof AudioInputStream ) {


            audioStreamFormat = ((AudioInputStream)audioStream).getFormat();
            encoding = audioStreamFormat.getEncoding();

            //$$ fb 2001-07-13: Bug 4391108
            if( (AudioFormat.Encoding.PCM_UNSIGNED.equals(encoding)) ||
                (AudioFormat.Encoding.PCM_SIGNED.equals(encoding)
                 && bigendian != audioStreamFormat.isBigEndian()) ) {

                                // plug in the transcoder to convert to PCM_SIGNED, bigendian
                                // NOTE: little endian AU is not common, so we're always converting
                                //       to big endian unless the passed in audioFileFormat is little.
                                // $$fb this NOTE is superseded. We always write big endian au files, this is by far the standard.
                codedAudioStream = AudioSystem.getAudioInputStream( new AudioFormat (
                                                                                     AudioFormat.Encoding.PCM_SIGNED,
                                                                                     audioStreamFormat.getSampleRate(),
                                                                                     audioStreamFormat.getSampleSizeInBits(),
                                                                                     audioStreamFormat.getChannels(),
                                                                                     audioStreamFormat.getFrameSize(),
                                                                                     audioStreamFormat.getFrameRate(),
                                                                                     bigendian),
                                                                    (AudioInputStream)audioStream );


            }
        }

        baos = new ByteArrayOutputStream();
        dos = new DataOutputStream(baos);


        if (bigendian) {
            dos.writeInt(AuFileFormat.AU_SUN_MAGIC);
            dos.writeInt(headerSize);
            dos.writeInt((int)dataSizeInBytes);
            dos.writeInt(encoding_local);
            dos.writeInt(sampleRate);
            dos.writeInt(channels);
        } else {
            dos.writeInt(AuFileFormat.AU_SUN_INV_MAGIC);
            dos.writeInt(big2little(headerSize));
            dos.writeInt(big2little((int)dataSizeInBytes));
            dos.writeInt(big2little(encoding_local));
            dos.writeInt(big2little(sampleRate));
            dos.writeInt(big2little(channels));
        }

        // Now create a new InputStream from headerStream and the InputStream
        // in audioStream

        dos.close();
        header = baos.toByteArray();
        headerStream = new ByteArrayInputStream( header );
        auStream = new SequenceInputStream(headerStream,codedAudioStream);

        return auStream;
    }

    private int writeAuFile(InputStream in, AuFileFormat auFileFormat, OutputStream out) throws IOException {

        int bytesRead = 0;
        int bytesWritten = 0;
        InputStream fileStream = getFileStream(auFileFormat, in);
        byte buffer[] = new byte[bisBufferSize];
        int maxLength = auFileFormat.getByteLength();

        while( (bytesRead = fileStream.read( buffer )) >= 0 ) {
            if (maxLength>0) {
                if( bytesRead < maxLength ) {
                    out.write( buffer, 0, (int)bytesRead );
                    bytesWritten += bytesRead;
                    maxLength -= bytesRead;
                } else {
                    out.write( buffer, 0, (int)maxLength );
                    bytesWritten += maxLength;
                    maxLength = 0;
                    break;
                }
            } else {
                out.write( buffer, 0, (int)bytesRead );
                bytesWritten += bytesRead;
            }
        }

        return bytesWritten;
    }


}
