/*
**
** 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 "Radio"
//#define LOG_NDEBUG 0

#include <utils/Log.h>
#include <utils/threads.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/IMemory.h>

#include <radio/Radio.h>
#include <radio/IRadio.h>
#include <radio/IRadioService.h>
#include <radio/IRadioClient.h>
#include <radio/RadioCallback.h>

namespace android {

namespace {
    sp<IRadioService>          gRadioService;
    const int                  kRadioServicePollDelay = 500000; // 0.5s
    const char*                kRadioServiceName      = "media.radio";
    Mutex                      gLock;

    class DeathNotifier : public IBinder::DeathRecipient
    {
    public:
        DeathNotifier() {
        }

        virtual void binderDied(const wp<IBinder>& who __unused) {
            ALOGV("binderDied");
            Mutex::Autolock _l(gLock);
            gRadioService.clear();
            ALOGW("Radio service died!");
        }
    };

    sp<DeathNotifier>         gDeathNotifier;
}; // namespace anonymous

const sp<IRadioService> Radio::getRadioService()
{
    Mutex::Autolock _l(gLock);
    if (gRadioService.get() == 0) {
        sp<IServiceManager> sm = defaultServiceManager();
        sp<IBinder> binder;
        do {
            binder = sm->getService(String16(kRadioServiceName));
            if (binder != 0) {
                break;
            }
            ALOGW("RadioService not published, waiting...");
            usleep(kRadioServicePollDelay);
        } while(true);
        if (gDeathNotifier == NULL) {
            gDeathNotifier = new DeathNotifier();
        }
        binder->linkToDeath(gDeathNotifier);
        gRadioService = interface_cast<IRadioService>(binder);
    }
    ALOGE_IF(gRadioService == 0, "no RadioService!?");
    return gRadioService;
}

// Static methods
status_t Radio::listModules(struct radio_properties *properties,
                            uint32_t *numModules)
{
    ALOGV("listModules()");
    const sp<IRadioService> service = getRadioService();
    if (service == 0) {
        return NO_INIT;
    }
    return service->listModules(properties, numModules);
}

sp<Radio> Radio::attach(radio_handle_t handle,
                        const struct radio_band_config *config,
                        bool withAudio,
                        const sp<RadioCallback>& callback)
{
    ALOGV("attach()");
    sp<Radio> radio;
    const sp<IRadioService> service = getRadioService();
    if (service == 0) {
        return radio;
    }
    radio = new Radio(handle, callback);
    status_t status = service->attach(handle, radio, config, withAudio, radio->mIRadio);

    if (status == NO_ERROR && radio->mIRadio != 0) {
        IInterface::asBinder(radio->mIRadio)->linkToDeath(radio);
    } else {
        ALOGW("Error %d connecting to radio service", status);
        radio.clear();
    }
    return radio;
}



// Radio
Radio::Radio(radio_handle_t /*handle*/, const sp<RadioCallback>& callback)
    : mCallback(callback)
{
}

Radio::~Radio()
{
    if (mIRadio != 0) {
        mIRadio->detach();
    }
}


void Radio::detach() {
    ALOGV("detach()");
    Mutex::Autolock _l(mLock);
    mCallback.clear();
    if (mIRadio != 0) {
        mIRadio->detach();
        IInterface::asBinder(mIRadio)->unlinkToDeath(this);
        mIRadio = 0;
    }
}

status_t Radio::setConfiguration(const struct radio_band_config *config)
{
    Mutex::Autolock _l(mLock);
    if (mIRadio == 0) {
        return NO_INIT;
    }
    return mIRadio->setConfiguration(config);
}

status_t Radio::getConfiguration(struct radio_band_config *config)
{
    Mutex::Autolock _l(mLock);
    if (mIRadio == 0) {
        return NO_INIT;
    }
    return mIRadio->getConfiguration(config);
}

status_t Radio::setMute(bool mute)
{
    Mutex::Autolock _l(mLock);
    if (mIRadio == 0) {
        return NO_INIT;
    }
    return mIRadio->setMute(mute);
}

status_t Radio::getMute(bool *mute)
{
    Mutex::Autolock _l(mLock);
    if (mIRadio == 0) {
        return NO_INIT;
    }
    return mIRadio->getMute(mute);
}

status_t Radio::scan(radio_direction_t direction, bool skipSubchannel)
{
    Mutex::Autolock _l(mLock);
    if (mIRadio == 0) {
        return NO_INIT;
    }
    return mIRadio->scan(direction, skipSubchannel);
}

status_t Radio::step(radio_direction_t direction, bool skipSubchannel)
{
    Mutex::Autolock _l(mLock);
    if (mIRadio == 0) {
        return NO_INIT;
    }
    return mIRadio->step(direction, skipSubchannel);
}

status_t Radio::tune(unsigned int channel, unsigned int subChannel)
{
    Mutex::Autolock _l(mLock);
    if (mIRadio == 0) {
        return NO_INIT;
    }
    return mIRadio->tune(channel, subChannel);
}

status_t Radio::cancel()
{
    Mutex::Autolock _l(mLock);
    if (mIRadio == 0) {
        return NO_INIT;
    }
    return mIRadio->cancel();
}

status_t Radio::getProgramInformation(struct radio_program_info *info)
{
    Mutex::Autolock _l(mLock);
    if (mIRadio == 0) {
        return NO_INIT;
    }
    return mIRadio->getProgramInformation(info);
}

status_t Radio::hasControl(bool *hasControl)
{
    Mutex::Autolock _l(mLock);
    if (mIRadio == 0) {
        return NO_INIT;
    }
    return mIRadio->hasControl(hasControl);
}


// BpRadioClient
void Radio::onEvent(const sp<IMemory>& eventMemory)
{
    Mutex::Autolock _l(mLock);
    if (eventMemory == 0 || eventMemory->pointer() == NULL) {
        return;
    }

    struct radio_event *event = (struct radio_event *)eventMemory->pointer();
    // restore local metadata pointer from offset
    switch (event->type) {
    case RADIO_EVENT_TUNED:
    case RADIO_EVENT_AF_SWITCH:
        if (event->info.metadata != NULL) {
            event->info.metadata =
                    (radio_metadata_t *)((char *)event + (size_t)event->info.metadata);
        }
        break;
    case RADIO_EVENT_METADATA:
        if (event->metadata != NULL) {
            event->metadata =
                    (radio_metadata_t *)((char *)event + (size_t)event->metadata);
        }
        break;
    default:
        break;
    }

    if (mCallback != 0) {
        mCallback->onEvent(event);
    }
}


//IBinder::DeathRecipient
void Radio::binderDied(const wp<IBinder>& who __unused) {
    Mutex::Autolock _l(mLock);
    ALOGW("Radio server binder Died ");
    mIRadio = 0;
    struct radio_event event;
    memset(&event, 0, sizeof(struct radio_event));
    event.type = RADIO_EVENT_SERVER_DIED;
    event.status = DEAD_OBJECT;
    if (mCallback != 0) {
        mCallback->onEvent(&event);
    }
}

}; // namespace android
