/*
 * 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());
}

Health::~Health() {}

//
// 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::setChargingPolicy(BatteryChargingPolicy in_value) {
    ::android::status_t err = battery_monitor_.setChargingPolicy(static_cast<int>(in_value));

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

ndk::ScopedAStatus Health::getChargingPolicy(BatteryChargingPolicy* out) {
    return GetProperty(&battery_monitor_, ::android::BATTERY_PROP_CHARGING_POLICY,
                       BatteryChargingPolicy::DEFAULT, out);
}

ndk::ScopedAStatus Health::getBatteryHealthData(BatteryHealthData* out) {
    if (auto res =
                GetProperty<int64_t>(&battery_monitor_, ::android::BATTERY_PROP_MANUFACTURING_DATE,
                                     0, &out->batteryManufacturingDateSeconds);
        !res.isOk()) {
        LOG(WARNING) << "Cannot get Manufacturing_date: " << res.getDescription();
    }
    if (auto res = GetProperty<int64_t>(&battery_monitor_, ::android::BATTERY_PROP_FIRST_USAGE_DATE,
                                        0, &out->batteryFirstUsageSeconds);
        !res.isOk()) {
        LOG(WARNING) << "Cannot get First_usage_date: " << res.getDescription();
    }
    if (auto res = GetProperty<int64_t>(&battery_monitor_, ::android::BATTERY_PROP_STATE_OF_HEALTH,
                                        0, &out->batteryStateOfHealth);
        !res.isOk()) {
        LOG(WARNING) << "Cannot get Battery_state_of_health: " << res.getDescription();
    }
    return ndk::ScopedAStatus::ok();
}

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();

    *out = battery_monitor_.getHealthInfo();

    // 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
