/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed 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 android.media.midi;

import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.util.Log;

import dalvik.system.CloseGuard;

import libcore.io.IoUtils;

import java.io.Closeable;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * This class is used for sending data to a port on a MIDI device
 */
public final class MidiInputPort extends MidiReceiver implements Closeable {
    private static final String TAG = "MidiInputPort";

    private IMidiDeviceServer mDeviceServer;
    private final IBinder mToken;
    private final int mPortNumber;
    private ParcelFileDescriptor mParcelFileDescriptor;
    private FileOutputStream mOutputStream;

    private final CloseGuard mGuard = CloseGuard.get();
    private boolean mIsClosed;

    // buffer to use for sending data out our output stream
    private final byte[] mBuffer = new byte[MidiPortImpl.MAX_PACKET_SIZE];

    /* package */ MidiInputPort(IMidiDeviceServer server, IBinder token,
            ParcelFileDescriptor pfd, int portNumber) {
        super(MidiPortImpl.MAX_PACKET_DATA_SIZE);

        mDeviceServer = server;
        mToken = token;
        mParcelFileDescriptor = pfd;
        mPortNumber = portNumber;
        mOutputStream = new FileOutputStream(pfd.getFileDescriptor());
        mGuard.open("close");
    }

    /* package */ MidiInputPort(ParcelFileDescriptor pfd, int portNumber) {
        this(null, null, pfd, portNumber);
    }

    /**
     * Returns the port number of this port
     *
     * @return the port's port number
     */
    public final int getPortNumber() {
        return mPortNumber;
    }

    @Override
    public void onSend(byte[] msg, int offset, int count, long timestamp) throws IOException {
        if (offset < 0 || count < 0 || offset + count > msg.length) {
            throw new IllegalArgumentException("offset or count out of range");
        }
        if (count > MidiPortImpl.MAX_PACKET_DATA_SIZE) {
            throw new IllegalArgumentException("count exceeds max message size");
        }

        synchronized (mBuffer) {
            if (mOutputStream == null) {
                throw new IOException("MidiInputPort is closed");
            }
            int length = MidiPortImpl.packData(msg, offset, count, timestamp, mBuffer);
            mOutputStream.write(mBuffer, 0, length);
        }
    }

    @Override
    public void onFlush() throws IOException {
        synchronized (mBuffer) {
            if (mOutputStream == null) {
                throw new IOException("MidiInputPort is closed");
            }
            int length = MidiPortImpl.packFlush(mBuffer);
            mOutputStream.write(mBuffer, 0, length);
        }
    }

    // used by MidiDevice.connectInputPort() to connect our socket directly to another device
    /* package */ ParcelFileDescriptor claimFileDescriptor() {
        synchronized (mGuard) {
            ParcelFileDescriptor pfd;
            synchronized (mBuffer) {
                pfd = mParcelFileDescriptor;
                if (pfd == null) return null;
                IoUtils.closeQuietly(mOutputStream);
                mParcelFileDescriptor = null;
                mOutputStream = null;
            }

            // Set mIsClosed = true so we will not call mDeviceServer.closePort() in close().
            // MidiDevice.MidiConnection.close() will do the cleanup instead.
            mIsClosed = true;
            return pfd;
        }
    }

    // used by MidiDevice.MidiConnection to close this port after the connection is closed
    /* package */ IBinder getToken() {
        return mToken;
    }

    // used by MidiDevice.MidiConnection to close this port after the connection is closed
    /* package */ IMidiDeviceServer getDeviceServer() {
        return mDeviceServer;
    }

    @Override
    public void close() throws IOException {
        synchronized (mGuard) {
            if (mIsClosed) return;
            mGuard.close();
            synchronized (mBuffer) {
                if (mParcelFileDescriptor != null) {
                    mParcelFileDescriptor.close();
                    mParcelFileDescriptor = null;
                }
                if (mOutputStream != null) {
                    mOutputStream.close();
                    mOutputStream = null;
                }
            }
            if (mDeviceServer != null) {
                try {
                    mDeviceServer.closePort(mToken);
                } catch (RemoteException e) {
                    Log.e(TAG, "RemoteException in MidiInputPort.close()");
                }
            }
            mIsClosed = true;
        }
    }

    @Override
    protected void finalize() throws Throwable {
        try {
            mGuard.warnIfOpen();
            // not safe to make binder calls from finalize()
            mDeviceServer = null;
            close();
        } finally {
            super.finalize();
        }
    }
}
