/*
 * Copyright (C) Texas Instruments - http://www.ti.com/
 *
 * 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.
 */

/**
* @file SensorListener.cpp
*
* This file listens and propogates sensor events to CameraHal.
*
*/

#define LOG_TAG "CameraHAL"

#include "SensorListener.h"
#include "CameraHal.h"

#include <stdint.h>
#include <math.h>
#include <sys/types.h>

namespace android {

/*** static declarations ***/
static const float RADIANS_2_DEG = (float) (180 / M_PI);
// measured values on device...might need tuning
static const int DEGREES_90_THRESH = 50;
static const int DEGREES_180_THRESH = 170;
static const int DEGREES_270_THRESH = 250;

static int sensor_events_listener(int fd, int events, void* data)
{
    SensorListener* listener = (SensorListener*) data;
    ssize_t num_sensors;
    ASensorEvent sen_events[8];
    while ((num_sensors = listener->mSensorEventQueue->read(sen_events, 8)) > 0) {
        for (int i = 0; i < num_sensors; i++) {
            if (sen_events[i].type == Sensor::TYPE_ACCELEROMETER) {
                float x = sen_events[i].vector.azimuth;
                float y = sen_events[i].vector.pitch;
                float z = sen_events[i].vector.roll;
                float radius = 0;
                int tilt = 0, orient = 0;

                CAMHAL_LOGVA("ACCELEROMETER EVENT");
                CAMHAL_LOGVB(" azimuth = %f pitch = %f roll = %f",
                             sen_events[i].vector.azimuth,
                             sen_events[i].vector.pitch,
                             sen_events[i].vector.roll);
                // see http://en.wikipedia.org/wiki/Spherical_coordinate_system#Cartesian_coordinates
                // about conversion from cartesian to spherical for orientation calculations
                radius = (float) sqrt(x * x + y * y + z * z);
                tilt = (int) asinf(z / radius) * RADIANS_2_DEG;
                orient = (int) atan2f(-x, y) * RADIANS_2_DEG;

                if (orient < 0) {
                    orient += 360;
                }

                if (orient >= DEGREES_270_THRESH) {
                    orient = 270;
                } else if (orient >= DEGREES_180_THRESH) {
                    orient = 180;
                } else if (orient >= DEGREES_90_THRESH) {
                    orient = 90;
                } else {
                    orient = 0;
                }
                listener->handleOrientation(orient, tilt);
                CAMHAL_LOGVB(" tilt = %d orientation = %d", tilt, orient);
            } else if (sen_events[i].type == Sensor::TYPE_GYROSCOPE) {
                CAMHAL_LOGVA("GYROSCOPE EVENT");
            }
        }
    }

    if (num_sensors < 0 && num_sensors != -EAGAIN) {
        CAMHAL_LOGEB("reading events failed: %s", strerror(-num_sensors));
    }

    return 1;
}

/****** public - member functions ******/
SensorListener::SensorListener() {
    LOG_FUNCTION_NAME;

    sensorsEnabled = 0;
    mOrientationCb = NULL;
    mSensorEventQueue = NULL;
    mSensorLooperThread = NULL;

    LOG_FUNCTION_NAME_EXIT;
}

SensorListener::~SensorListener() {
    LOG_FUNCTION_NAME;

    CAMHAL_LOGDA("Kill looper thread");
    if (mSensorLooperThread.get()) {
        // 1. Request exit
        // 2. Wake up looper which should be polling for an event
        // 3. Wait for exit
        mSensorLooperThread->requestExit();
        mSensorLooperThread->wake();
        mSensorLooperThread->join();
        mSensorLooperThread.clear();
        mSensorLooperThread = NULL;
    }

    CAMHAL_LOGDA("Kill looper");
    if (mLooper.get()) {
        mLooper->removeFd(mSensorEventQueue->getFd());
        mLooper.clear();
        mLooper = NULL;
    }
    CAMHAL_LOGDA("SensorListener destroyed");

    LOG_FUNCTION_NAME_EXIT;
}

status_t SensorListener::initialize() {
    status_t ret = NO_ERROR;
    SensorManager& mgr(SensorManager::getInstance());

    LOG_FUNCTION_NAME;

    sp<Looper> mLooper;

    mSensorEventQueue = mgr.createEventQueue();
    if (mSensorEventQueue == NULL) {
        CAMHAL_LOGEA("createEventQueue returned NULL");
        ret = NO_INIT;
        goto out;
    }

    mLooper = new Looper(false);
    mLooper->addFd(mSensorEventQueue->getFd(), 0, ALOOPER_EVENT_INPUT, sensor_events_listener, this);

    if (mSensorLooperThread.get() == NULL)
            mSensorLooperThread = new SensorLooperThread(mLooper.get());

    if (mSensorLooperThread.get() == NULL) {
        CAMHAL_LOGEA("Couldn't create sensor looper thread");
        ret = NO_MEMORY;
        goto out;
    }

    ret = mSensorLooperThread->run("sensor looper thread", PRIORITY_URGENT_DISPLAY);
    if (ret == INVALID_OPERATION){
        CAMHAL_LOGDA("thread already running ?!?");
    } else if (ret != NO_ERROR) {
        CAMHAL_LOGEA("couldn't run thread");
        goto out;
    }

 out:
    LOG_FUNCTION_NAME_EXIT;
    return ret;
}

void SensorListener::setCallbacks(orientation_callback_t orientation_cb, void *cookie) {
    LOG_FUNCTION_NAME;

    if (orientation_cb) {
        mOrientationCb = orientation_cb;
    }
    mCbCookie = cookie;

    LOG_FUNCTION_NAME_EXIT;
}

void SensorListener::handleOrientation(uint32_t orientation, uint32_t tilt) {
    LOG_FUNCTION_NAME;

    Mutex::Autolock lock(&mLock);

    if (mOrientationCb && (sensorsEnabled & SENSOR_ORIENTATION)) {
        mOrientationCb(orientation, tilt, mCbCookie);
    }

    LOG_FUNCTION_NAME_EXIT;
}

void SensorListener::enableSensor(sensor_type_t type) {
    Sensor const* sensor;
    SensorManager& mgr(SensorManager::getInstance());

    LOG_FUNCTION_NAME;

    Mutex::Autolock lock(&mLock);

    if ((type & SENSOR_ORIENTATION) && !(sensorsEnabled & SENSOR_ORIENTATION)) {
        sensor = mgr.getDefaultSensor(Sensor::TYPE_ACCELEROMETER);
        CAMHAL_LOGDB("orientation = %p (%s)", sensor, sensor->getName().string());
        mSensorEventQueue->enableSensor(sensor);
        mSensorEventQueue->setEventRate(sensor, ms2ns(100));
        sensorsEnabled |= SENSOR_ORIENTATION;
    }

    LOG_FUNCTION_NAME_EXIT;
}

void SensorListener::disableSensor(sensor_type_t type) {
    Sensor const* sensor;
    SensorManager& mgr(SensorManager::getInstance());

    LOG_FUNCTION_NAME;

    Mutex::Autolock lock(&mLock);

    if ((type & SENSOR_ORIENTATION) && (sensorsEnabled & SENSOR_ORIENTATION)) {
        sensor = mgr.getDefaultSensor(Sensor::TYPE_ACCELEROMETER);
        CAMHAL_LOGDB("orientation = %p (%s)", sensor, sensor->getName().string());
        mSensorEventQueue->disableSensor(sensor);
        sensorsEnabled &= ~SENSOR_ORIENTATION;
    }

    LOG_FUNCTION_NAME_EXIT;
}

} // namespace android
