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

#include "apptohostevent.h"

#include "contexthub.h"
#include "log.h"

namespace android {

/* AppToHostEvent *************************************************************/

std::unique_ptr<AppToHostEvent> AppToHostEvent::FromBytes(
        const std::vector<uint8_t>& buffer) {
    auto event = std::unique_ptr<AppToHostEvent>(new AppToHostEvent());
    event->Populate(buffer);
    if (!event->IsValid()) {
        return nullptr;
    }

    return event;
}

uint64_t AppToHostEvent::GetAppId() const {
    return GetTypedData()->appId;
}

uint8_t AppToHostEvent::GetDataLen() const {
    return GetTypedData()->dataLen;
}

const uint8_t *AppToHostEvent::GetDataPtr() const {
    return (reinterpret_cast<const uint8_t*>(GetTypedData())
              + sizeof(struct HostHubRawPacket));
}

bool AppToHostEvent::CheckAppId(SensorType sensor_type) const {
    // Make sure the app ID matches what we expect for the sensor type, bail out
    // early if it doesn't
    switch (sensor_type) {
      case SensorType::Accel:
      case SensorType::Gyro:
        if (GetAppId() != kAppIdBoschBmi160Bmm150) {
            return false;
        }
        break;

      case SensorType::Proximity:
        if (GetAppId() != kAppIdAmsTmd2772 && GetAppId() != kAppIdRohmRpr0521 &&
            GetAppId() != kAppIdAmsTmd4903) {
            return false;
        }
        break;

      case SensorType::Barometer:
        if (GetAppId() != kAppIdBoschBmp280) {
            return false;
        }
        break;

      case SensorType::AmbientLightSensor:
        if (GetAppId() != kAppIdAmsTmd4903) {
            return false;
        }
        break;

      default:
        return false;
    }

    return true;
}

bool AppToHostEvent::CheckEventHeader(SensorType sensor_type) const {
    if (GetDataLen() < sizeof(struct SensorAppEventHeader)) {
        return false;
    }

    if (!CheckAppId(sensor_type)) {
        return false;
    }

    return true;
}

bool AppToHostEvent::IsCalibrationEventForSensor(SensorType sensor_type) const {
    if (!CheckEventHeader(sensor_type)) {
        return false;
    }

    // If we made it this far, we only need to confirm the message ID
    auto header = reinterpret_cast<const struct SensorAppEventHeader *>(
        GetDataPtr());
    return (header->msgId == SENSOR_APP_MSG_CALIBRATION_RESULT);
}

bool AppToHostEvent::IsTestEventForSensor(SensorType sensor_type) const {
    if (!CheckEventHeader(sensor_type)) {
        return false;
    }

    // If we made it this far, we only need to confirm the message ID
    auto header = reinterpret_cast<const struct SensorAppEventHeader *>(
        GetDataPtr());
    return (header->msgId == SENSOR_APP_MSG_TEST_RESULT);
}

bool AppToHostEvent::IsValid() const {
    const HostHubRawPacket *packet = GetTypedData();
    if (!packet) {
        return false;
    }

    // dataLen should specify the amount of data that follows the event type
    // and HostHubRawPacket headers
    if (event_data.size() < (sizeof(uint32_t) + sizeof(struct HostHubRawPacket)
                               + packet->dataLen)) {
        LOGW("Invalid/short AppToHost event of size %zu", event_data.size());
        return false;
    }

    return true;
}

const HostHubRawPacket *AppToHostEvent::GetTypedData() const {
    // After the event type header (uint32_t), we should have struct
    // HostHubRawPacket
    if (event_data.size() < sizeof(uint32_t) + sizeof(struct HostHubRawPacket)) {
        LOGW("Invalid/short AppToHost event of size %zu", event_data.size());
        return nullptr;
    }
    return reinterpret_cast<const HostHubRawPacket *>(
        event_data.data() + sizeof(uint32_t));
}

}  // namespace android
