/*
 * Copyright (C) 2015 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 "VehicleNetwork.Lib"

#include <assert.h>
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
#include <utils/threads.h>

#include <hardware/vehicle.h>

#include <VehicleNetwork.h>

namespace android {

VehicleNetworkEventMessageHandler::VehicleNetworkEventMessageHandler(const sp<Looper>& looper,
            sp<VehicleNetworkListener>& listener) :
            mLooper(looper),
            mListener(listener) {

}

VehicleNetworkEventMessageHandler::~VehicleNetworkEventMessageHandler() {
    Mutex::Autolock autoLock(mLock);
    mEvents.clear();
    for (VehicleHalError* e : mHalErrors) {
        delete e;
    }
    mHalErrors.clear();
    mHalRestartEvents.clear();
    mSetValueEvents.clear();
}

void VehicleNetworkEventMessageHandler::handleHalEvents(sp<VehiclePropValueListHolder>& events) {
    Mutex::Autolock autoLock(mLock);
    mEvents.push_back(events);
    mLooper->sendMessage(this, Message(EVENT_EVENTS));
}

void VehicleNetworkEventMessageHandler::handleHalError(int32_t errorCode, int32_t property,
        int32_t operation) {
    Mutex::Autolock autoLock(mLock);
    VehicleHalError* error = new VehicleHalError(errorCode, property, operation);
    if (error == NULL) {
        ALOGE("VehicleNetworkEventMessageHandler::handleHalError, new failed");
        return;
    }
    mHalErrors.push_back(error);
    mLooper->sendMessage(this, Message(EVENT_HAL_ERROR));
}

void VehicleNetworkEventMessageHandler::handleHalRestart(bool inMocking) {
    Mutex::Autolock autoLock(mLock);
    mHalRestartEvents.push_back(inMocking);
    mLooper->sendMessage(this, Message(EVENT_HAL_RESTART));
}

void VehicleNetworkEventMessageHandler::handleOnPropertySet(const vehicle_prop_value_t& value) {
    Mutex::Autolock autoLock(mLock);
    mSetValueEvents.push_back(VehiclePropValueUtil::allocVehiclePropValue(value));
    mLooper->sendMessage(this, Message(EVENT_ON_SET));
}

void VehicleNetworkEventMessageHandler::doHandleHalEvents() {
    sp<VehiclePropValueListHolder> values;
    do {
        Mutex::Autolock autoLock(mLock);
        if (mEvents.size() > 0) {
            auto itr = mEvents.begin();
            values = *itr;
            mEvents.erase(itr);
        }
    } while (false);
    if (values.get() != NULL) {
        mListener->onEvents(values);
    }
}

void VehicleNetworkEventMessageHandler::doHandleHalError() {
    VehicleHalError* error = NULL;
    do {
        Mutex::Autolock autoLock(mLock);
        if (mHalErrors.size() > 0) {
            auto itr = mHalErrors.begin();
            error = *itr;
            mHalErrors.erase(itr);
        }
    } while (false);
    if (error != NULL) {
        mListener->onHalError(error->errorCode, error->property, error->operation);
        delete error;
    }
}

void VehicleNetworkEventMessageHandler::doHandleHalRestart() {
    bool shouldDispatch = false;
    bool inMocking = false;
    do {
        Mutex::Autolock autoLock(mLock);
        if (mHalRestartEvents.size() > 0) {
            auto itr = mHalRestartEvents.begin();
            inMocking = *itr;
            mHalRestartEvents.erase(itr);
            shouldDispatch = true;
        }
    } while (false);
    if (shouldDispatch) {
        mListener->onHalRestart(inMocking);
    }
}

void VehicleNetworkEventMessageHandler::doHandleOnPropertySet() {
    vehicle_prop_value_t* value = nullptr;
    {
        Mutex::Autolock autoLock(mLock);
        if (!mSetValueEvents.empty()) {
            auto itr = mSetValueEvents.begin();
            value = *itr;
            mSetValueEvents.erase(itr);
        }
    }
    if (value != nullptr) {
        mListener->onPropertySet(*value);
        VehiclePropValueUtil::deleteMembers(value);
        delete value;
    }
}

void VehicleNetworkEventMessageHandler::handleMessage(const Message& message) {
    switch (message.what) {
        case EVENT_EVENTS:
            doHandleHalEvents();
            break;
        case EVENT_HAL_ERROR:
            doHandleHalError();
            break;
        case EVENT_HAL_RESTART:
            doHandleHalRestart();
            break;
        case EVENT_ON_SET:
            doHandleOnPropertySet();
            break;
    }
}

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

static const int MAX_SERVICE_RETRY = 4;

sp<VehicleNetwork> VehicleNetwork::createVehicleNetwork(sp<VehicleNetworkListener>& listener) {
    sp<IBinder> binder;
    int retry = 0;
    while (true) {
        binder = defaultServiceManager()->getService(String16(IVehicleNetwork::SERVICE_NAME));
        if (binder.get() != NULL) {
            break;
        }
        retry++;
        if (retry > MAX_SERVICE_RETRY) {
            ALOGE("cannot get VNS, will crash");
            break;
        }
    }
    ASSERT_ALWAYS_ON_NO_MEMORY(binder.get());
    sp<IVehicleNetwork> ivn(interface_cast<IVehicleNetwork>(binder));
    sp<VehicleNetwork> vn;
    vn = new VehicleNetwork(ivn, listener);
    ASSERT_ALWAYS_ON_NO_MEMORY(vn.get());
    // in case thread pool is not started, start it.
    ProcessState::self()->startThreadPool();
    return vn;
}

VehicleNetwork::VehicleNetwork(sp<IVehicleNetwork>& vehicleNetwork,
        sp<VehicleNetworkListener> &listener) :
        mService(vehicleNetwork),
        mClientListener(listener) {
}

VehicleNetwork::~VehicleNetwork() {
    sp<IVehicleNetwork> service = getService();
    IInterface::asBinder(service)->unlinkToDeath(this);
    service->stopHalRestartMonitoring(this);
    mHandlerThread->quit();
}

void VehicleNetwork::onFirstRef() {
    Mutex::Autolock autoLock(mLock);
    mHandlerThread = new HandlerThread();
    status_t r = mHandlerThread->start("VNS.NATIVE_LOOP");
    if (r != NO_ERROR) {
        ALOGE("cannot start handler thread, error:%d", r);
        return;
    }
    sp<VehicleNetworkEventMessageHandler> handler(
            new VehicleNetworkEventMessageHandler(mHandlerThread->getLooper(), mClientListener));
    ASSERT_ALWAYS_ON_NO_MEMORY(handler.get());
    mEventHandler = handler;
    IInterface::asBinder(mService)->linkToDeath(this);
    mService->startHalRestartMonitoring(this);
}

status_t VehicleNetwork::setInt32Property(int32_t property, int32_t value) {
    vehicle_prop_value_t v;
    v.prop = property;
    v.value_type = VEHICLE_VALUE_TYPE_INT32;
    v.value.int32_value = value;
    return setProperty(v);
}

status_t VehicleNetwork::getInt32Property(int32_t property, int32_t* value, int64_t* timestamp) {
    vehicle_prop_value_t v;
    v.prop = property;
    // do not check error as it is always safe to access members for this data type.
    // saves one if for normal flow.
    status_t r = getProperty(&v);
    *value = v.value.int32_value;
    *timestamp = v.timestamp;
    return r;
}

status_t VehicleNetwork::setInt64Property(int32_t property, int64_t value) {
    vehicle_prop_value_t v;
    v.prop = property;
    v.value_type = VEHICLE_VALUE_TYPE_INT64;
    v.value.int64_value = value;
    return setProperty(v);
}

status_t VehicleNetwork::getInt64Property(int32_t property, int64_t* value, int64_t* timestamp) {
    vehicle_prop_value_t v;
    v.prop = property;
    status_t r = getProperty(&v);
    *value = v.value.int64_value;
    *timestamp = v.timestamp;
    return r;
}

status_t VehicleNetwork::setFloatProperty(int32_t property, float value) {
    vehicle_prop_value_t v;
    v.prop = property;
    v.value_type = VEHICLE_VALUE_TYPE_FLOAT;
    v.value.float_value = value;
    return setProperty(v);
}

status_t VehicleNetwork::getFloatProperty(int32_t property, float* value, int64_t* timestamp) {
    vehicle_prop_value_t v;
    v.prop = property;
    status_t r = getProperty(&v);
    *value = v.value.float_value;
    *timestamp = v.timestamp;
    return r;
}

status_t VehicleNetwork::setStringProperty(int32_t property, const String8& value) {
    vehicle_prop_value_t v;
    v.prop = property;
    v.value_type = VEHICLE_VALUE_TYPE_STRING;
    v.value.str_value.data = (uint8_t*)value.string();
    v.value.str_value.len = value.length();
    return setProperty(v);
}

status_t VehicleNetwork::getStringProperty(int32_t property, String8& value, int64_t* timestamp) {
    vehicle_prop_value_t v;
    v.prop = property;
    v.value.str_value.len = 0;
    status_t r = getProperty(&v);
    if (r == NO_ERROR) {
        value.setTo((char*)v.value.str_value.data, v.value.str_value.len);
    }
    *timestamp = v.timestamp;
    return r;
}

sp<VehiclePropertiesHolder> VehicleNetwork::listProperties(int32_t property) {
    return getService()->listProperties(property);
}

status_t VehicleNetwork::setProperty(const vehicle_prop_value_t& value) {
    return getService()->setProperty(value);
}

status_t VehicleNetwork::getProperty(vehicle_prop_value_t* value) {
    return getService()->getProperty(value);
}

status_t VehicleNetwork::subscribe(int32_t property, float sampleRate, int32_t zones,
                                   int32_t flags) {
    return getService()->subscribe(this, property, sampleRate, zones, flags);
}

void VehicleNetwork::unsubscribe(int32_t property) {
    getService()->unsubscribe(this, property);
}

status_t VehicleNetwork::injectEvent(const vehicle_prop_value_t& value) {
    return getService()->injectEvent(value);
}

status_t VehicleNetwork::startMocking(const sp<IVehicleNetworkHalMock>& mock) {
    return getService()->startMocking(mock);
}

void VehicleNetwork::stopMocking(const sp<IVehicleNetworkHalMock>& mock) {
    getService()->stopMocking(mock);
}

status_t VehicleNetwork::startErrorListening() {
    return getService()->startErrorListening(this);
}

void VehicleNetwork::stopErrorListening() {
    getService()->stopErrorListening(this);
}

void VehicleNetwork::binderDied(const wp<IBinder>& who) {
    ALOGE("service died");
    do {
        Mutex::Autolock autoLock(mLock);
        sp<IBinder> ibinder = who.promote();
        ibinder->unlinkToDeath(this);
        sp<IBinder> binder = defaultServiceManager()->getService(
                String16(IVehicleNetwork::SERVICE_NAME));
        mService = interface_cast<IVehicleNetwork>(binder);
        IInterface::asBinder(mService)->linkToDeath(this);
        mService->startHalRestartMonitoring(this);
    } while (false);
    onHalRestart(false);
}

sp<IVehicleNetwork> VehicleNetwork::getService() {
    Mutex::Autolock autoLock(mLock);
    return mService;
}

sp<VehicleNetworkEventMessageHandler> VehicleNetwork::getEventHandler() {
    Mutex::Autolock autoLock(mLock);
    return mEventHandler;
}

void VehicleNetwork::onEvents(sp<VehiclePropValueListHolder>& events) {
    getEventHandler()->handleHalEvents(events);
}

void VehicleNetwork::onHalError(int32_t errorCode, int32_t property, int32_t operation) {
    getEventHandler()->handleHalError(errorCode, property, operation);
}

void VehicleNetwork::onHalRestart(bool inMocking) {
    getEventHandler()->handleHalRestart(inMocking);
}

void VehicleNetwork::onPropertySet(const vehicle_prop_value_t& value) {
    getEventHandler()->handleOnPropertySet(value);
}
}; // namespace android
