/*
 * Copyright (C) 2021 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 "health-impl/Health.h"

#include <android-base/file.h>
#include <android-base/logging.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
#include <android/hardware/health/translate-ndk.h>
#include <health/utils.h>

#include "LinkedCallback.h"
#include "health-convert.h"

using std::string_literals::operator""s;

namespace aidl::android::hardware::health {

namespace {
// Wrap LinkedCallback::OnCallbackDied() into a void(void*).
void OnCallbackDiedWrapped(void* cookie) {
    LinkedCallback* linked = reinterpret_cast<LinkedCallback*>(cookie);
    linked->OnCallbackDied();
}
}  // namespace

/*
// If you need to call healthd_board_init, construct the Health instance with
// the healthd_config after calling healthd_board_init:
class MyHealth : public Health {
  protected:
    MyHealth() : Health(CreateConfig()) {}
  private:
    static std::unique_ptr<healthd_config> CreateConfig() {
      auto config = std::make_unique<healthd_config>();
      ::android::hardware::health::InitHealthdConfig(config.get());
      healthd_board_init(config.get());
      return std::move(config);
    }
};
*/
Health::Health(std::string_view instance_name, std::unique_ptr<struct healthd_config>&& config)
    : instance_name_(instance_name),
      healthd_config_(std::move(config)),
      death_recipient_(AIBinder_DeathRecipient_new(&OnCallbackDiedWrapped)) {
    battery_monitor_.init(healthd_config_.get());
}

//
// Getters.
//

template <typename T>
static ndk::ScopedAStatus GetProperty(::android::BatteryMonitor* monitor, int id, T defaultValue,
                                      T* out) {
    *out = defaultValue;
    struct ::android::BatteryProperty prop;
    ::android::status_t err = monitor->getProperty(static_cast<int>(id), &prop);
    if (err == ::android::OK) {
        *out = static_cast<T>(prop.valueInt64);
    } else {
        LOG(DEBUG) << "getProperty(" << id << ")"
                   << " fails: (" << err << ") " << ::android::statusToString(err);
    }

    switch (err) {
        case ::android::OK:
            return ndk::ScopedAStatus::ok();
        case ::android::NAME_NOT_FOUND:
            return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
        default:
            return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
                    IHealth::STATUS_UNKNOWN, ::android::statusToString(err).c_str());
    }
}

ndk::ScopedAStatus Health::getChargeCounterUah(int32_t* out) {
    return GetProperty<int32_t>(&battery_monitor_, ::android::BATTERY_PROP_CHARGE_COUNTER, 0, out);
}

ndk::ScopedAStatus Health::getCurrentNowMicroamps(int32_t* out) {
    return GetProperty<int32_t>(&battery_monitor_, ::android::BATTERY_PROP_CURRENT_NOW, 0, out);
}

ndk::ScopedAStatus Health::getCurrentAverageMicroamps(int32_t* out) {
    return GetProperty<int32_t>(&battery_monitor_, ::android::BATTERY_PROP_CURRENT_AVG, 0, out);
}

ndk::ScopedAStatus Health::getCapacity(int32_t* out) {
    return GetProperty<int32_t>(&battery_monitor_, ::android::BATTERY_PROP_CAPACITY, 0, out);
}

ndk::ScopedAStatus Health::getEnergyCounterNwh(int64_t* out) {
    return GetProperty<int64_t>(&battery_monitor_, ::android::BATTERY_PROP_ENERGY_COUNTER, 0, out);
}

ndk::ScopedAStatus Health::getChargeStatus(BatteryStatus* out) {
    return GetProperty(&battery_monitor_, ::android::BATTERY_PROP_BATTERY_STATUS,
                       BatteryStatus::UNKNOWN, out);
}

ndk::ScopedAStatus Health::getDiskStats(std::vector<DiskStats>*) {
    // This implementation does not support DiskStats. An implementation may extend this
    // class and override this function to support disk stats.
    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}

ndk::ScopedAStatus Health::getStorageInfo(std::vector<StorageInfo>*) {
    // This implementation does not support StorageInfo. An implementation may extend this
    // class and override this function to support storage info.
    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}

ndk::ScopedAStatus Health::getHealthInfo(HealthInfo* out) {
    battery_monitor_.updateValues();

    // TODO(b/177269435): BatteryMonitor should store AIDL HealthInfo instead.
    auto health_info_2_1 = battery_monitor_.getHealthInfo_2_1();
    if (!::android::h2a::translate(health_info_2_1, out)) {
        return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
                IHealth::STATUS_UNKNOWN, "Cannot translate HIDL HealthInfo to AIDL");
    }

    // Fill in storage infos; these aren't retrieved by BatteryMonitor.
    if (auto res = getStorageInfo(&out->storageInfos); !res.isOk()) {
        if (res.getServiceSpecificError() == 0 &&
            res.getExceptionCode() != EX_UNSUPPORTED_OPERATION) {
            return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
                    IHealth::STATUS_UNKNOWN,
                    ("getStorageInfo fails: " + res.getDescription()).c_str());
        }
        LOG(DEBUG) << "getHealthInfo: getStorageInfo fails with service-specific error, clearing: "
                   << res.getDescription();
        out->storageInfos = {};
    }
    if (auto res = getDiskStats(&out->diskStats); !res.isOk()) {
        if (res.getServiceSpecificError() == 0 &&
            res.getExceptionCode() != EX_UNSUPPORTED_OPERATION) {
            return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
                    IHealth::STATUS_UNKNOWN,
                    ("getDiskStats fails: " + res.getDescription()).c_str());
        }
        LOG(DEBUG) << "getHealthInfo: getDiskStats fails with service-specific error, clearing: "
                   << res.getDescription();
        out->diskStats = {};
    }

    // A subclass may want to update health info struct before returning it.
    UpdateHealthInfo(out);

    return ndk::ScopedAStatus::ok();
}

binder_status_t Health::dump(int fd, const char**, uint32_t) {
    battery_monitor_.dumpState(fd);

    ::android::base::WriteStringToFd("\ngetHealthInfo -> ", fd);
    HealthInfo health_info;
    auto res = getHealthInfo(&health_info);
    if (res.isOk()) {
        ::android::base::WriteStringToFd(health_info.toString(), fd);
    } else {
        ::android::base::WriteStringToFd(res.getDescription(), fd);
    }

    fsync(fd);
    return STATUS_OK;
}

std::optional<bool> Health::ShouldKeepScreenOn() {
    if (!healthd_config_->screen_on) {
        return std::nullopt;
    }

    HealthInfo health_info;
    auto res = getHealthInfo(&health_info);
    if (!res.isOk()) {
        return std::nullopt;
    }

    ::android::BatteryProperties props = {};
    convert(health_info, &props);
    return healthd_config_->screen_on(&props);
}

namespace {
bool IsDeadObjectLogged(const ndk::ScopedAStatus& ret) {
    if (ret.isOk()) return false;
    if (ret.getStatus() == ::STATUS_DEAD_OBJECT) return true;
    LOG(ERROR) << "Cannot call healthInfoChanged on callback: " << ret.getDescription();
    return false;
}
}  // namespace

//
// Subclass helpers / overrides
//

void Health::UpdateHealthInfo(HealthInfo* /* health_info */) {
    /*
        // Sample code for a subclass to implement this:
        // If you need to modify values (e.g. batteryChargeTimeToFullNowSeconds), do it here.
        health_info->batteryChargeTimeToFullNowSeconds = calculate_charge_time_seconds();

        // If you need to call healthd_board_battery_update, modify its signature
        // and implementation to operate on HealthInfo directly, then call:
        healthd_board_battery_update(health_info);
    */
}

//
// Methods that handle callbacks.
//

ndk::ScopedAStatus Health::registerCallback(const std::shared_ptr<IHealthInfoCallback>& callback) {
    if (callback == nullptr) {
        // For now, this shouldn't happen because argument is not nullable.
        return ndk::ScopedAStatus::fromExceptionCode(EX_NULL_POINTER);
    }

    {
        std::lock_guard<decltype(callbacks_lock_)> lock(callbacks_lock_);
        callbacks_.emplace_back(LinkedCallback::Make(ref<Health>(), callback));
        // unlock
    }

    HealthInfo health_info;
    if (auto res = getHealthInfo(&health_info); !res.isOk()) {
        LOG(WARNING) << "Cannot call getHealthInfo: " << res.getDescription();
        // No health info to send, so return early.
        return ndk::ScopedAStatus::ok();
    }

    if (auto res = callback->healthInfoChanged(health_info); IsDeadObjectLogged(res)) {
        (void)unregisterCallback(callback);
    }
    return ndk::ScopedAStatus::ok();
}

ndk::ScopedAStatus Health::unregisterCallback(
        const std::shared_ptr<IHealthInfoCallback>& callback) {
    if (callback == nullptr) {
        // For now, this shouldn't happen because argument is not nullable.
        return ndk::ScopedAStatus::fromExceptionCode(EX_NULL_POINTER);
    }

    std::lock_guard<decltype(callbacks_lock_)> lock(callbacks_lock_);

    auto matches = [callback](const auto& linked) {
        return linked->callback()->asBinder() == callback->asBinder();  // compares binder object
    };
    auto it = std::remove_if(callbacks_.begin(), callbacks_.end(), matches);
    bool removed = (it != callbacks_.end());
    callbacks_.erase(it, callbacks_.end());  // calls unlinkToDeath on deleted callbacks.
    return removed ? ndk::ScopedAStatus::ok()
                   : ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}

// A combination of the HIDL version
//   android::hardware::health::V2_1::implementation::Health::update() and
//   android::hardware::health::V2_1::implementation::BinderHealth::update()
ndk::ScopedAStatus Health::update() {
    HealthInfo health_info;
    if (auto res = getHealthInfo(&health_info); !res.isOk()) {
        LOG(DEBUG) << "Cannot call getHealthInfo for update(): " << res.getDescription();
        // Propagate service specific errors. If there's none, report unknown error.
        if (res.getServiceSpecificError() != 0 ||
            res.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
            return res;
        }
        return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
                IHealth::STATUS_UNKNOWN, res.getDescription().c_str());
    }
    battery_monitor_.logValues();
    OnHealthInfoChanged(health_info);
    return ndk::ScopedAStatus::ok();
}

void Health::OnHealthInfoChanged(const HealthInfo& health_info) {
    // Notify all callbacks
    std::unique_lock<decltype(callbacks_lock_)> lock(callbacks_lock_);
    // is_dead notifies a callback and return true if it is dead.
    auto is_dead = [&](const auto& linked) {
        auto res = linked->callback()->healthInfoChanged(health_info);
        return IsDeadObjectLogged(res);
    };
    auto it = std::remove_if(callbacks_.begin(), callbacks_.end(), is_dead);
    callbacks_.erase(it, callbacks_.end());  // calls unlinkToDeath on deleted callbacks.
    lock.unlock();

    // Let HalHealthLoop::OnHealthInfoChanged() adjusts uevent / wakealarm periods
}

void Health::BinderEvent(uint32_t /*epevents*/) {
    if (binder_fd_ >= 0) {
        ABinderProcess_handlePolledCommands();
    }
}

void Health::OnInit(HalHealthLoop* hal_health_loop, struct healthd_config* config) {
    LOG(INFO) << instance_name_ << " instance initializing with healthd_config...";

    // Similar to HIDL's android::hardware::health::V2_1::implementation::HalHealthLoop::Init,
    // copy configuration parameters to |config| for HealthLoop (e.g. uevent / wake alarm periods)
    *config = *healthd_config_.get();

    binder_status_t status = ABinderProcess_setupPolling(&binder_fd_);

    if (status == ::STATUS_OK && binder_fd_ >= 0) {
        std::shared_ptr<Health> thiz = ref<Health>();
        auto binder_event = [thiz](auto*, uint32_t epevents) { thiz->BinderEvent(epevents); };
        if (hal_health_loop->RegisterEvent(binder_fd_, binder_event, EVENT_NO_WAKEUP_FD) != 0) {
            PLOG(ERROR) << instance_name_ << " instance: Register for binder events failed";
        }
    }

    std::string health_name = IHealth::descriptor + "/"s + instance_name_;
    CHECK_EQ(STATUS_OK, AServiceManager_addService(this->asBinder().get(), health_name.c_str()))
            << instance_name_ << ": Failed to register HAL";

    LOG(INFO) << instance_name_ << ": Hal init done";
}

// Unlike hwbinder, for binder, there's no need to explicitly call flushCommands()
// in PrepareToWait(). See b/139697085.

}  // namespace aidl::android::hardware::health
