/*
 * Copyright (C) 2018 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 <pixelhealth/CycleCountBackupRestore.h>

namespace hardware {
namespace google {
namespace pixel {
namespace health {

static constexpr int kBackupTrigger = 20;

CycleCountBackupRestore::CycleCountBackupRestore(int nb_buckets, const char *sysfs_path,
                                                 const char *persist_path, const char *serial_path)
    : nb_buckets_(nb_buckets),
      saved_soc_(-1),
      soc_inc_(0),
      sysfs_path_(sysfs_path),
      persist_path_(persist_path),
      serial_path_(serial_path) {
    sw_bins_ = new int[nb_buckets]();
    hw_bins_ = new int[nb_buckets]();
}

void CycleCountBackupRestore::Restore() {
    if (CheckSerial()) {
        Read(persist_path_, sw_bins_);
    }
    Read(sysfs_path_, hw_bins_);
    UpdateAndSave();
}

bool CycleCountBackupRestore::CheckSerial() {
    std::string device_battery_serial;
    std::string persist_battery_serial;

    if (serial_path_.empty())
        return true;

    if (!android::base::ReadFileToString(serial_path_, &device_battery_serial)) {
        LOG(ERROR) << "Failed to read " << serial_path_;
        return true;
    }

    if (!android::base::ReadFileToString(kPersistSerial, &persist_battery_serial)) {
        LOG(ERROR) << "Failed to read " << kPersistSerial;
    }

    if (device_battery_serial != persist_battery_serial) {
        // Battery pack has been changed or first time,
        // cycle counts on the pack are the ones to save
        if (!android::base::WriteStringToFile(device_battery_serial, kPersistSerial)) {
            LOG(ERROR) << "Write to " << kPersistSerial << " error: " << strerror(errno);
        }
        return false;
    }

    return true;
}

void CycleCountBackupRestore::Backup(int battery_level) {
    if (saved_soc_ == -1) {
        saved_soc_ = battery_level;
        return;
    }
    // Cycle counts only increases on increasing level
    if (battery_level > saved_soc_) {
        soc_inc_ += battery_level - saved_soc_;
    }
    saved_soc_ = battery_level;
    // To avoid writting file too often just rate limit it
    if (soc_inc_ >= kBackupTrigger) {
        Read(sysfs_path_, hw_bins_);
        UpdateAndSave();
        soc_inc_ = 0;
    }
}

void CycleCountBackupRestore::Read(const std::string &path, int *bins) {
    std::string buffer;

    if (!android::base::ReadFileToString(path, &buffer)) {
        LOG(ERROR) << "Failed to read " << path;
        return;
    }

    buffer = ::android::base::Trim(buffer);
    std::vector<std::string> counts = android::base::Split(buffer, " ");
    if (counts.size() != (size_t)nb_buckets_) {
        LOG(ERROR) << "data format \"" << buffer << "\" is wrong in " << path;
    } else {
        LOG(INFO) << "Read: \"" << buffer << "\" from " << path;
        for (int i = 0; i < nb_buckets_; ++i) {
            bins[i] = std::stoi(counts[i]);
        }
    }
}

void CycleCountBackupRestore::Write(int *bins, const std::string &path) {
    std::string str_data = "";

    for (int i = 0; i < nb_buckets_; ++i) {
        if (i) {
            str_data += " ";
        }
        str_data += std::to_string(bins[i]);
    }

    LOG(INFO) << "Write: \"" << str_data << "\" to " << path;
    if (!android::base::WriteStringToFile(str_data, path))
        LOG(ERROR) << "Write to " << path << " error: " << strerror(errno);
}

void CycleCountBackupRestore::UpdateAndSave() {
    bool backup = false;
    bool restore = false;
    for (int i = 0; i < nb_buckets_; i++) {
        if (hw_bins_[i] < sw_bins_[i]) {
            hw_bins_[i] = sw_bins_[i];
            restore = true;
        } else if (hw_bins_[i] > sw_bins_[i]) {
            sw_bins_[i] = hw_bins_[i];
            backup = true;
        }
    }
    if (restore)
        Write(hw_bins_, sysfs_path_);
    if (backup)
        Write(sw_bins_, persist_path_);
}

}  // namespace health
}  // namespace pixel
}  // namespace google
}  // namespace hardware
