/*
 * Copyright (C) 2018 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.
 */

#define LOG_TAG "NativeMIDI"

#include <poll.h>
#include <unistd.h>

#include <binder/Binder.h>
#include <android_util_Binder.h>
#include <utils/Log.h>

#include <core_jni_helpers.h>

#include "android/media/midi/BpMidiDeviceServer.h"
#include "MidiDeviceInfo.h"

#include "include/amidi/AMidi.h"
#include "amidi_internal.h"

using namespace android::media::midi;

using android::IBinder;
using android::BBinder;
using android::OK;
using android::sp;
using android::status_t;
using android::base::unique_fd;
using android::binder::Status;

struct AMIDI_Port {
    std::atomic_int     state;      // One of the port status constants below.
    const AMidiDevice  *device;    // Points to the AMidiDevice associated with the port.
    sp<IBinder>         binderToken;// The Binder token associated with the port.
    unique_fd           ufd;        // The unique file descriptor associated with the port.
};

/*
 * Port Status Constants
 */
enum {
    MIDI_PORT_STATE_CLOSED = 0,
    MIDI_PORT_STATE_OPEN_IDLE,
    MIDI_PORT_STATE_OPEN_ACTIVE
};

/*
 * Port Type Constants
 */
enum {
    PORTTYPE_OUTPUT = 0,
    PORTTYPE_INPUT = 1
};

/* TRANSFER PACKET FORMAT (as defined in MidiPortImpl.java)
 *
 * Transfer packet format is as follows (see MidiOutputPort.mThread.run() to see decomposition):
 * |oc|md|md| ......... |md|ts|ts|ts|ts|ts|ts|ts|ts|
 *  ^ +--------------------+-----------------------+
 *  |  ^                    ^
 *  |  |                    |
 *  |  |                    + timestamp (8 bytes)
 *  |  |
 *  |  + MIDI data bytes (numBytes bytes)
 *  |
 *  + OpCode (AMIDI_OPCODE_DATA)
 *
 *  NOTE: The socket pair is configured to use SOCK_SEQPACKET mode.
 *  SOCK_SEQPACKET, for a sequenced-packet socket that is connection-oriented, preserves message
 *  boundaries, and delivers messages in the order that they were sent.
 *  So 'read()' always returns a whole message.
 */
#define AMIDI_PACKET_SIZE       1024
#define AMIDI_PACKET_OVERHEAD   9
#define AMIDI_BUFFER_SIZE       (AMIDI_PACKET_SIZE - AMIDI_PACKET_OVERHEAD)

// JNI IDs (see android_media_midi.cpp)
namespace android { namespace midi {
//  MidiDevice Fields
extern jfieldID gFidMidiNativeHandle;         // MidiDevice.mNativeHandle
extern jfieldID gFidMidiDeviceServerBinder;   // MidiDevice.mDeviceServerBinder
extern jfieldID gFidMidiDeviceInfo;           // MidiDevice.mDeviceInfo

//  MidiDeviceInfo Fields
extern jfieldID mFidMidiDeviceId;             // MidiDeviceInfo.mId
}}
using namespace android::midi;

static std::mutex openMutex; // Ensure that the device can be connected just once to 1 thread

//// Handy debugging function.
//static void AMIDI_logBuffer(const uint8_t *data, size_t numBytes) {
//    for (size_t index = 0; index < numBytes; index++) {
//      ALOGI("  data @%zu [0x%X]", index, data[index]);
//    }
//}

/*
 * Device Functions
 */
/**
 * Retrieves information for the native MIDI device.
 *
 * device           The Native API token for the device. This value is obtained from the
 *                  AMidiDevice_fromJava().
 * outDeviceInfoPtr Receives the associated device info.
 *
 * Returns AMEDIA_OK or a negative error code.
 *  - AMEDIA_ERROR_INVALID_PARAMETER
 *  AMEDIA_ERROR_UNKNOWN
 */
static media_status_t AMIDI_getDeviceInfo(const AMidiDevice *device,
        AMidiDeviceInfo *outDeviceInfoPtr) {
    if (device == nullptr) {
        return AMEDIA_ERROR_INVALID_PARAMETER;
    }

    MidiDeviceInfo deviceInfo;
    Status txResult = device->server->getDeviceInfo(&deviceInfo);
    if (!txResult.isOk()) {
        ALOGE("%s server exception code: %d", __func__, txResult.exceptionCode());
        return AMEDIA_ERROR_UNKNOWN;
    }

    outDeviceInfoPtr->type = deviceInfo.getType();
    outDeviceInfoPtr->inputPortCount = deviceInfo.getInputPortNames().size();
    outDeviceInfoPtr->outputPortCount = deviceInfo.getOutputPortNames().size();
    outDeviceInfoPtr->defaultProtocol = deviceInfo.getDefaultProtocol();

    return AMEDIA_OK;
}

media_status_t AMIDI_API AMidiDevice_fromJava(JNIEnv *env, jobject j_midiDeviceObj,
        AMidiDevice** devicePtrPtr)
{
    if (j_midiDeviceObj == nullptr) {
        ALOGE("AMidiDevice_fromJava() invalid MidiDevice object.");
        return AMEDIA_ERROR_INVALID_OBJECT;
    }

    {
        std::lock_guard<std::mutex> guard(openMutex);

        long handle = env->GetLongField(j_midiDeviceObj, gFidMidiNativeHandle);
        if (handle != 0) {
            // Already opened by someone.
            return AMEDIA_ERROR_INVALID_OBJECT;
        }

        jobject serverBinderObj = env->GetObjectField(j_midiDeviceObj, gFidMidiDeviceServerBinder);
        sp<IBinder> serverBinder = android::ibinderForJavaObject(env, serverBinderObj);
        if (serverBinder.get() == nullptr) {
            ALOGE("AMidiDevice_fromJava couldn't connect to native MIDI server.");
            return AMEDIA_ERROR_UNKNOWN;
        }

        // don't check allocation failures, just abort..
        AMidiDevice* devicePtr = new AMidiDevice;
        devicePtr->server = new BpMidiDeviceServer(serverBinder);
        jobject midiDeviceInfoObj = env->GetObjectField(j_midiDeviceObj, gFidMidiDeviceInfo);
        devicePtr->deviceId = env->GetIntField(midiDeviceInfoObj, mFidMidiDeviceId);

        // Synchronize with the associated Java MidiDevice.
        env->SetLongField(j_midiDeviceObj, gFidMidiNativeHandle, (long)devicePtr);
        env->GetJavaVM(&devicePtr->javaVM);
        devicePtr->midiDeviceObj = env->NewGlobalRef(j_midiDeviceObj);

        if (AMIDI_getDeviceInfo(devicePtr, &devicePtr->deviceInfo) != AMEDIA_OK) {
            // This is weird, but maybe not fatal?
            ALOGE("AMidiDevice_fromJava couldn't retrieve attributes of native device.");
        }

        *devicePtrPtr = devicePtr;
    }

    return AMEDIA_OK;
}

media_status_t AMIDI_API AMidiDevice_release(const AMidiDevice *device)
{
    if (device == nullptr || device->midiDeviceObj == nullptr) {
        return AMEDIA_ERROR_INVALID_PARAMETER;
    }

    JNIEnv* env;
    jint err = device->javaVM->GetEnv((void**)&env, JNI_VERSION_1_6);
    LOG_ALWAYS_FATAL_IF(err != JNI_OK, "AMidiDevice_release Error accessing JNIEnv err:%d", err);

    // Synchronize with the associated Java MidiDevice.
    {
        std::lock_guard<std::mutex> guard(openMutex);
        long handle = env->GetLongField(device->midiDeviceObj, gFidMidiNativeHandle);
        if (handle == 0) {
            // Not opened as native.
            ALOGE("AMidiDevice_release() device not opened in native client.");
            return AMEDIA_ERROR_INVALID_OBJECT;
        }

        env->SetLongField(device->midiDeviceObj, gFidMidiNativeHandle, 0L);
    }
    env->DeleteGlobalRef(device->midiDeviceObj);

    delete device;

    return AMEDIA_OK;
}

int32_t AMIDI_API AMidiDevice_getType(const AMidiDevice *device) {
    if (device == nullptr) {
        return AMEDIA_ERROR_INVALID_PARAMETER;
    }
    return device->deviceInfo.type;
}

ssize_t AMIDI_API AMidiDevice_getNumInputPorts(const AMidiDevice *device) {
    if (device == nullptr) {
        return AMEDIA_ERROR_INVALID_PARAMETER;
    }
    return device->deviceInfo.inputPortCount;
}

ssize_t AMIDI_API AMidiDevice_getNumOutputPorts(const AMidiDevice *device) {
    if (device == nullptr) {
        return AMEDIA_ERROR_INVALID_PARAMETER;
    }
    return device->deviceInfo.outputPortCount;
}

AMidiDevice_Protocol AMIDI_API AMidiDevice_getDefaultProtocol(const AMidiDevice *device) {
    if (device == nullptr) {
        return AMIDI_DEVICE_PROTOCOL_UNKNOWN;
    }
    return static_cast<AMidiDevice_Protocol>(device->deviceInfo.defaultProtocol);
}

/*
 * Port Helpers
 */
static media_status_t AMIDI_openPort(const AMidiDevice *device, int32_t portNumber, int type,
        AMIDI_Port **portPtr) {
    if (device == nullptr) {
        return AMEDIA_ERROR_INVALID_PARAMETER;
    }

    sp<BBinder> portToken(new BBinder());
    unique_fd ufd;
    Status txResult = type == PORTTYPE_OUTPUT
            ? device->server->openOutputPort(portToken, portNumber, &ufd)
            : device->server->openInputPort(portToken, portNumber, &ufd);
    if (!txResult.isOk()) {
        ALOGE("%s server exception code: %d", __func__, txResult.exceptionCode());
        return AMEDIA_ERROR_UNKNOWN;
    }

    AMIDI_Port *port = new AMIDI_Port;
    port->state = MIDI_PORT_STATE_OPEN_IDLE;
    port->device = device;
    port->binderToken = portToken;
    port->ufd = std::move(ufd);

    *portPtr = port;

    return AMEDIA_OK;
}

static void AMIDI_closePort(AMIDI_Port *port) {
    if (port == nullptr) {
        return;
    }

    int portState = MIDI_PORT_STATE_OPEN_IDLE;
    while (!port->state.compare_exchange_weak(portState, MIDI_PORT_STATE_CLOSED)) {
        if (portState == MIDI_PORT_STATE_CLOSED) {
            return; // Already closed
        }
    }

    Status txResult = port->device->server->closePort(port->binderToken);
    if (!txResult.isOk()) {
        ALOGE("%s server exception code: %d", __func__, txResult.exceptionCode());
    }

    delete port;
}

/*
 * Output (receiving) API
 */
media_status_t AMIDI_API AMidiOutputPort_open(const AMidiDevice *device, int32_t portNumber,
        AMidiOutputPort **outOutputPortPtr) {
    return AMIDI_openPort(device, portNumber, PORTTYPE_OUTPUT, (AMIDI_Port**)outOutputPortPtr);
}

/*
 *  A little RAII (https://en.wikipedia.org/wiki/Resource_acquisition_is_initialization)
 *  class to ensure that the port state is correct irrespective of errors.
 */
class MidiReceiver {
public:
    MidiReceiver(AMIDI_Port *port) : mPort(port) {}

    ~MidiReceiver() {
        // flag the port state to idle
        mPort->state.store(MIDI_PORT_STATE_OPEN_IDLE);
    }

    ssize_t receive(int32_t *opcodePtr, uint8_t *buffer, size_t maxBytes,
            size_t *numBytesReceivedPtr, int64_t *timestampPtr) {
        int portState = MIDI_PORT_STATE_OPEN_IDLE;
        // check to see if the port is idle, then set to active
        if (!mPort->state.compare_exchange_strong(portState, MIDI_PORT_STATE_OPEN_ACTIVE)) {
            // The port not idle or has been closed.
            return AMEDIA_ERROR_UNKNOWN;
        }

        struct pollfd checkFds[1] = { { mPort->ufd, POLLIN, 0 } };
        if (poll(checkFds, 1, 0) < 1) {
            // Nothing there
            return 0;
        }

        uint8_t readBuffer[AMIDI_PACKET_SIZE];
        ssize_t readCount = TEMP_FAILURE_RETRY(read(mPort->ufd, readBuffer, sizeof(readBuffer)));
        if (readCount < 1) {
            return  AMEDIA_ERROR_UNKNOWN;
        }

        // see Packet Format definition at the top of this file.
        size_t numMessageBytes = 0;
        *opcodePtr = readBuffer[0];
        if (*opcodePtr == AMIDI_OPCODE_DATA && readCount >= AMIDI_PACKET_OVERHEAD) {
            numMessageBytes = readCount - AMIDI_PACKET_OVERHEAD;
            numMessageBytes = std::min(maxBytes, numMessageBytes);
            memcpy(buffer, readBuffer + 1, numMessageBytes);
            if (timestampPtr != nullptr) {
                memcpy(timestampPtr, readBuffer + readCount - sizeof(uint64_t),
                        sizeof(*timestampPtr));
            }
        }
        *numBytesReceivedPtr = numMessageBytes;
        return 1;
    }

private:
    AMIDI_Port *mPort;
};

ssize_t AMIDI_API AMidiOutputPort_receive(const AMidiOutputPort *outputPort, int32_t *opcodePtr,
         uint8_t *buffer, size_t maxBytes, size_t* numBytesReceivedPtr, int64_t *timestampPtr) {

    if (outputPort == nullptr || buffer == nullptr) {
        return -EINVAL;
    }

   return MidiReceiver((AMIDI_Port*)outputPort).receive(opcodePtr, buffer, maxBytes,
           numBytesReceivedPtr, timestampPtr);
}

void AMIDI_API AMidiOutputPort_close(const AMidiOutputPort *outputPort) {
    AMIDI_closePort((AMIDI_Port*)outputPort);
}

/*
 * Input (sending) API
 */
media_status_t AMIDI_API AMidiInputPort_open(const AMidiDevice *device, int32_t portNumber,
        AMidiInputPort **outInputPortPtr) {
    return AMIDI_openPort(device, portNumber, PORTTYPE_INPUT, (AMIDI_Port**)outInputPortPtr);
}

void AMIDI_API AMidiInputPort_close(const AMidiInputPort *inputPort) {
    AMIDI_closePort((AMIDI_Port*)inputPort);
}

static ssize_t AMIDI_makeSendBuffer(
        uint8_t *buffer, const uint8_t *data, size_t numBytes, uint64_t timestamp) {
    // Error checking will happen in the caller since this isn't an API function.
    buffer[0] = AMIDI_OPCODE_DATA;
    memcpy(buffer + 1, data, numBytes);
    memcpy(buffer + 1 + numBytes, &timestamp, sizeof(timestamp));
    return numBytes + AMIDI_PACKET_OVERHEAD;
}

ssize_t AMIDI_API AMidiInputPort_send(const AMidiInputPort *inputPort, const uint8_t *buffer,
                            size_t numBytes) {
    return AMidiInputPort_sendWithTimestamp(inputPort, buffer, numBytes, 0);
}

ssize_t AMIDI_API AMidiInputPort_sendWithTimestamp(const AMidiInputPort *inputPort,
        const uint8_t *data, size_t numBytes, int64_t timestamp) {
    if (inputPort == nullptr || data == nullptr || numBytes < 0 || timestamp < 0) {
        return AMEDIA_ERROR_INVALID_PARAMETER;
    }

    if (numBytes == 0) {
        return 0;
    }

    // AMIDI_logBuffer(data, numBytes);

    uint8_t writeBuffer[AMIDI_BUFFER_SIZE + AMIDI_PACKET_OVERHEAD];
    size_t numSent = 0;
    while (numSent < numBytes) {
        size_t blockSize = AMIDI_BUFFER_SIZE;
        blockSize = std::min(blockSize, numBytes - numSent);

        ssize_t numTransferBytes =
                AMIDI_makeSendBuffer(writeBuffer, data + numSent, blockSize, timestamp);
        ssize_t numWritten = TEMP_FAILURE_RETRY(write(((AMIDI_Port*)inputPort)->ufd, writeBuffer,
                                                      numTransferBytes));
        if (numWritten < 0) {
            break;  // error so bail out.
        }
        if (numWritten < numTransferBytes) {
            ALOGE("AMidiInputPort_sendWithTimestamp Couldn't write MIDI data buffer."
                  " requested:%zu, written%zu",numTransferBytes, numWritten);
            break;  // bail
        }

        numSent += numWritten  - AMIDI_PACKET_OVERHEAD;
    }

    return numSent;
}

media_status_t AMIDI_API AMidiInputPort_sendFlush(const AMidiInputPort *inputPort) {
    if (inputPort == nullptr) {
        return AMEDIA_ERROR_INVALID_PARAMETER;
    }

    uint8_t opCode = AMIDI_OPCODE_FLUSH;
    ssize_t numTransferBytes = 1;
    ssize_t numWritten = TEMP_FAILURE_RETRY(write(((AMIDI_Port*)inputPort)->ufd, &opCode,
                                                  numTransferBytes));

    if (numWritten < numTransferBytes) {
        ALOGE("AMidiInputPort_flush Couldn't write MIDI flush. requested:%zd, written:%zd",
                numTransferBytes, numWritten);
        return AMEDIA_ERROR_UNSUPPORTED;
    }

    return AMEDIA_OK;
}

