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

#define LOG_TAG "healthd-flounder"
#include <healthd/healthd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <cutils/klog.h>
#include <sys/types.h>
#include <sys/sysinfo.h>

/* Nominal voltage for ENERGY_COUNTER computation */
#define VOLTAGE_NOMINAL 3.7

#define POWER_SUPPLY_SUBSYSTEM "power_supply"
#define POWER_SUPPLY_SYSFS_PATH "/sys/class/" POWER_SUPPLY_SUBSYSTEM

#define MAX17050_PATH POWER_SUPPLY_SYSFS_PATH "/battery"
#define CHARGE_COUNTER_EXT_PATH MAX17050_PATH "/charge_counter_ext"

#define PALMAS_VOLTAGE_MONITOR_PATH POWER_SUPPLY_SYSFS_PATH "/palmas_voltage_monitor"
#define VOLTAGE_MONITOR_PATH PALMAS_VOLTAGE_MONITOR_PATH "/device/voltage_monitor"

#define BATTERY_FULL 100
#define BATTERY_LOW 15
#define BATTERY_CRITICAL_LOW_MV (3000)
#define BATTERY_DEAD_MV (2800)
#define NORMAL_MAX_SOC_DEC (2)
#define CRITICAL_LOW_FORCE_SOC_DROP (6)
#define UPDATE_PERIOD_MINIMUM_S (55)
#define BATTERY_OVERTEMP_THRESHOLD (550)
#define BATTERY_UNDERTEMP_THRESHOLD (0)

using namespace android;
static bool first_update_done;
static int lasttime_soc;
static unsigned int flounder_monitor_voltage;
static long last_update_time;
static bool force_decrease;

static int read_sysfs(const char *path, char *buf, size_t size) {
    char *cp = NULL;

    int fd = open(path, O_RDONLY, 0);
    if (fd == -1) {
        KLOG_ERROR(LOG_TAG, "Could not open '%s'\n", path);
        return -1;
    }

    ssize_t count = TEMP_FAILURE_RETRY(read(fd, buf, size));
    if (count > 0)
        cp = (char *)memrchr(buf, '\n', count);

    if (cp)
        *cp = '\0';
    else
        buf[0] = '\0';

    close(fd);
    return count;
}

static void write_sysfs(const char *path, char *s)
{
    char buf[80];
    int len;
    int fd = open(path, O_WRONLY);

    if (fd < 0) {
        strerror_r(errno, buf, sizeof(buf));
        KLOG_ERROR(LOG_TAG, "Error opening %s: %s\n", path, buf);
        return;
    }

    len = write(fd, s, strlen(s));
    if (len < 0) {
        strerror_r(errno, buf, sizeof(buf));
        KLOG_ERROR(LOG_TAG, "Error writing to %s: %s\n", path, buf);
    }

    close(fd);
}

static int64_t get_int64_field(const char *path) {
    const int SIZE = 21;
    char buf[SIZE];

    int64_t value = 0;
    if (read_sysfs(path, buf, SIZE) > 0) {
        value = strtoll(buf, NULL, 0);
    }
    return value;
}

static void flounder_status_check(struct BatteryProperties *props)
{
    if (props->batteryStatus == BATTERY_STATUS_UNKNOWN)
        props->batteryStatus = BATTERY_STATUS_DISCHARGING;
    else if (props->batteryStatus == BATTERY_STATUS_FULL &&
        props->batteryLevel < BATTERY_FULL)
        props->batteryStatus = BATTERY_STATUS_CHARGING;
}

static void flounder_health_check(struct BatteryProperties *props)
{
    if (props->batteryLevel >= BATTERY_FULL)
        props->batteryHealth = BATTERY_HEALTH_GOOD;
    else if (props->batteryLevel < BATTERY_LOW)
        props->batteryHealth = BATTERY_HEALTH_DEAD;
    else
        props->batteryHealth = BATTERY_HEALTH_GOOD;

    if (props->batteryHealth == BATTERY_HEALTH_GOOD){
        if (props->batteryTemperature > BATTERY_OVERTEMP_THRESHOLD)
            props->batteryHealth = BATTERY_HEALTH_OVERHEAT;
        else if(props->batteryTemperature < BATTERY_UNDERTEMP_THRESHOLD)
            props->batteryHealth = BATTERY_HEALTH_COLD;
    }
}

static void flounder_voltage_monitor_check(struct BatteryProperties *props)
{
    unsigned int monitor_voltage = 0;
    int vcell_mv;
    char voltage[10];

    if (props->batteryStatus != BATTERY_STATUS_CHARGING &&
        props->batteryStatus != BATTERY_STATUS_FULL && props->batteryLevel > 0) {
        vcell_mv = props->batteryVoltage;
        if (vcell_mv > BATTERY_CRITICAL_LOW_MV)
            monitor_voltage = BATTERY_CRITICAL_LOW_MV;
        else if (vcell_mv > BATTERY_DEAD_MV)
            monitor_voltage = BATTERY_DEAD_MV;
    }

    if (monitor_voltage != flounder_monitor_voltage) {
        snprintf(voltage, sizeof(voltage), "%d", monitor_voltage);
        write_sysfs(VOLTAGE_MONITOR_PATH, voltage);
        flounder_monitor_voltage = monitor_voltage;
    }
}

static void flounder_soc_adjust(struct BatteryProperties *props)
{
    int soc_decrease;
    int soc, vcell_mv;
    struct sysinfo info;
    long uptime = 0;
    int ret;

    ret = sysinfo(&info);
    if (ret) {
       KLOG_ERROR(LOG_TAG, "Fail to get sysinfo!!\n");
       uptime = last_update_time;
    } else
       uptime = info.uptime;

    if (!first_update_done) {
        if (props->batteryLevel >= BATTERY_FULL) {
            props->batteryLevel = BATTERY_FULL - 1;
            lasttime_soc = BATTERY_FULL - 1;
        } else {
            lasttime_soc = props->batteryLevel;
        }
        last_update_time = uptime;
        first_update_done = true;
    }

    if (props->batteryStatus == BATTERY_STATUS_FULL)
        soc = BATTERY_FULL;
    else if (props->batteryLevel >= BATTERY_FULL &&
             lasttime_soc < BATTERY_FULL)
        soc = BATTERY_FULL - 1;
    else
        soc = props->batteryLevel;

    if (props->batteryLevel > BATTERY_FULL)
        props->batteryLevel = BATTERY_FULL;
    else if (props->batteryLevel < 0)
        props->batteryLevel = 0;

    vcell_mv = props->batteryVoltage;
    if (props->batteryStatus == BATTERY_STATUS_DISCHARGING ||
        props->batteryStatus == BATTERY_STATUS_NOT_CHARGING ||
        props->batteryStatus == BATTERY_STATUS_UNKNOWN) {
        if (vcell_mv >= BATTERY_CRITICAL_LOW_MV) {
            force_decrease = false;
            soc_decrease = lasttime_soc - soc;
            if (soc_decrease < 0) {
                soc = lasttime_soc;
                goto done;
            }

            if (uptime > last_update_time &&
                uptime - last_update_time <= UPDATE_PERIOD_MINIMUM_S) {
                soc = lasttime_soc;
                goto done;
            }

            if (soc_decrease < 0)
                soc_decrease = 0;
            else if (soc_decrease > NORMAL_MAX_SOC_DEC)
                soc_decrease = NORMAL_MAX_SOC_DEC;

            soc = lasttime_soc - soc_decrease;
        } else if (vcell_mv < BATTERY_DEAD_MV) {
            soc = 0;
        } else {
            if (force_decrease &&
                uptime > last_update_time &&
                uptime - last_update_time <= UPDATE_PERIOD_MINIMUM_S) {
                soc = lasttime_soc;
                goto done;
            }

            soc_decrease = CRITICAL_LOW_FORCE_SOC_DROP;
            if (lasttime_soc <= soc_decrease)
               soc = 0;
            else
                soc = lasttime_soc - soc_decrease;
            force_decrease = true;
        }
    } else {
        force_decrease = false;
        if (soc > lasttime_soc)
            soc = lasttime_soc + 1;
    }
    last_update_time = uptime;
done:
    props->batteryLevel = lasttime_soc = soc;
}

static void flounder_bat_monitor(struct BatteryProperties *props)
{
    flounder_soc_adjust(props);
    flounder_health_check(props);
    flounder_status_check(props);
    flounder_voltage_monitor_check(props);
}

int healthd_board_battery_update(struct BatteryProperties *props)
{

    flounder_bat_monitor(props);

    // return 0 to log periodic polled battery status to kernel log
    return 0;
}

static int flounder_energy_counter(int64_t *energy)
{
    *energy = get_int64_field(CHARGE_COUNTER_EXT_PATH) * VOLTAGE_NOMINAL;
    return 0;
}

void healthd_board_init(struct healthd_config *config)
{
    config->energyCounter = flounder_energy_counter;
}
