// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <dirent.h>
#include <fcntl.h>
#include <fuchsia/hardware/power/c/fidl.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/fdio.h>
#include <lib/fdio/unsafe.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <zircon/syscalls.h>
#include <zircon/types.h>

#include <algorithm>

#include <fbl/algorithm.h>
#include <fbl/string_buffer.h>
#include <fbl/vector.h>

typedef struct {
  int type;
  char name[255];
  uint8_t state;
  zx_handle_t events;
  zx_handle_t fidl_channel;
} pwrdev_t;

struct arg_data {
  bool debug;
  bool poll_events;
};

static const char* type_to_string[] = {"AC", "battery"};

zx_status_t get_source_info(zx_handle_t channel, struct fuchsia_hardware_power_SourceInfo* info) {
  zx_status_t status, op_status;

  // If either fails return the error we see (0 is success, errors are negative)
  status = fuchsia_hardware_power_SourceGetPowerInfo(channel, &op_status, info);
  zx_status_t result = std::min(status, op_status);
  if (result != ZX_OK) {
    fprintf(stderr, "SourceGetPowerInfo failed (transport: %d, operation: %d)\n", status,
            op_status);
  }
  return result;
}

static const char* state_to_string[] = {"online", "discharging", "charging", "critical"};
static const char* state_offline = "offline/not present";
const char* get_state_string(uint32_t state, fbl::StringBuffer<256>* buf) {
  buf->Clear();
  for (size_t i = 0; i < countof(state_to_string); i++) {
    if (state & (1 << i)) {
      if (buf->length()) {
        buf->Append(", ");
      }
      buf->Append(state_to_string[i]);
    }
  }

  return (buf->length() > 0) ? buf->c_str() : state_offline;
}

static zx_status_t get_battery_info(zx_handle_t ch) {
  struct fuchsia_hardware_power_BatteryInfo binfo = {};
  zx_status_t op_status;
  zx_status_t status = fuchsia_hardware_power_SourceGetBatteryInfo(ch, &op_status, &binfo);
  if (status != ZX_OK) {
    printf("GetBatteryInfo returned %d\n", status);
    return status;
  }

  const char* unit = (binfo.unit == fuchsia_hardware_power_BatteryUnit_MW) ? "mW" : "mA";
  printf("             design capacity: %d %s\n", binfo.design_capacity, unit);
  printf("          last full capacity: %d %s\n", binfo.last_full_capacity, unit);
  printf("              design voltage: %d mV\n", binfo.design_voltage);
  printf("            warning capacity: %d %s\n", binfo.capacity_warning, unit);
  printf("                low capacity: %d %s\n", binfo.capacity_low, unit);
  printf("     low/warning granularity: %d %s\n", binfo.capacity_granularity_low_warning, unit);
  printf("    warning/full granularity: %d %s\n", binfo.capacity_granularity_warning_full, unit);
  printf("                present rate: %d %s\n", binfo.present_rate, unit);
  printf("          remaining capacity: %d %s\n", binfo.remaining_capacity, unit);
  printf("             present voltage: %d mV\n", binfo.present_voltage);
  printf("==========================================\n");
  printf("remaining battery percentage: %d %%\n",
         binfo.remaining_capacity * 100 / binfo.last_full_capacity);
  if (binfo.present_rate < 0) {
    printf("      remaining battery life: %.2f h\n",
           (float)binfo.remaining_capacity / (float)binfo.present_rate * -1);
  }
  putchar('\n');
  return ZX_OK;
}

void parse_arguments(int argc, char** argv, struct arg_data* args) {
  int opt;
  while ((opt = getopt(argc, argv, "p")) != -1) {
    switch (opt) {
      case 'p':
        args->poll_events = true;
        break;
      default:
        fprintf(stderr, "Invalid arg: %c\nUsage: %s [-p]\n", opt, argv[0]);
        exit(EXIT_FAILURE);
    }
  }
}

void handle_event(pwrdev_t& interface) {
  zx_status_t status;
  struct fuchsia_hardware_power_SourceInfo info;
  if ((status = get_source_info(interface.fidl_channel, &info)) != ZX_OK) {
    exit(EXIT_FAILURE);
  }

  fbl::StringBuffer<256> old_buf;
  fbl::StringBuffer<256> new_buf;
  printf("%s (%s): state change %s (%#x) -> %s (%#x)\n", interface.name,
         type_to_string[interface.type], get_state_string(interface.state, &old_buf),
         interface.state, get_state_string(info.state, &new_buf), info.state);

  if (interface.type == fuchsia_hardware_power_PowerType_BATTERY &&
      (info.state & fuchsia_hardware_power_POWER_STATE_ONLINE)) {
    if (get_battery_info(interface.fidl_channel) != ZX_OK) {
      exit(EXIT_FAILURE);
    }
  }

  interface.state = info.state;
}

void poll_events(const fbl::Vector<pwrdev_t>& interfaces) {
  zx_wait_item_t* items = new zx_wait_item_t[interfaces.size()];
  for (size_t i = 0; i < interfaces.size(); i++) {
    items[i].handle = interfaces[i].events;
    items[i].waitfor = ZX_USER_SIGNAL_0;
    items[i].pending = 0;
  }

  zx_status_t status;
  printf("waiting for events...\n\n");
  for (;;) {
    status = zx_object_wait_many(items, interfaces.size(), ZX_TIME_INFINITE);
    if (status != ZX_OK) {
      printf("zx_object_wait_many() returned %d\n", status);
      exit(EXIT_FAILURE);
    }

    for (size_t i = 0; i < interfaces.size(); i++) {
      if (items[i].pending & ZX_USER_SIGNAL_0) {
        handle_event(interfaces[i]);
      }
    }
  }
}

int main(int argc, char** argv) {
  struct arg_data args = {};
  parse_arguments(argc, argv, &args);

  struct dirent* de;
  DIR* dir = opendir("/dev/class/power");
  if (!dir) {
    printf("Failed to read /dev/class/power\n");
    exit(EXIT_FAILURE);
  }

  fbl::StringBuffer<256> state_str;
  fbl::Vector<pwrdev_t> interfaces;
  while ((de = readdir(dir)) != NULL) {
    int fd = openat(dirfd(dir), de->d_name, O_RDONLY);
    if (fd < 0) {
      printf("Failed to read %s, skipping: %d\n", de->d_name, fd);
      continue;
    }

    struct fuchsia_hardware_power_SourceInfo pinfo;
    zx_handle_t ch;
    zx_status_t status;
    zx_status_t op_status;

    status = fdio_get_service_handle(fd, &ch);
    if (status != ZX_OK) {
      printf("Failed to get service handle for %s, skipping: %d!\n", de->d_name, status);
      continue;
    }

    status = get_source_info(ch, &pinfo);
    if (status != ZX_OK) {
      printf("Failed to read from source %s, skipping\n", de->d_name);
      continue;
    }

    printf("[%s] type: %s, state: %s (%#x)\n", de->d_name, type_to_string[pinfo.type],
           get_state_string(pinfo.state, &state_str), pinfo.state);

    if (pinfo.type == fuchsia_hardware_power_PowerType_BATTERY &&
        (pinfo.state & fuchsia_hardware_power_POWER_STATE_ONLINE)) {
      if (get_battery_info(ch) != ZX_OK) {
        fprintf(stderr, "Couldn't read battery information for %s, skipping\n", de->d_name);
        continue;
      }
    }

    if (args.poll_events) {
      zx_handle_t h = ZX_HANDLE_INVALID;
      status = fuchsia_hardware_power_SourceGetStateChangeEvent(ch, &op_status, &h);
      if (status != ZX_OK || op_status != ZX_OK) {
        printf("failed to get event: %d / %d\n", status, op_status);
        return status;
      }

      pwrdev_t dev = {};
      dev.type = pinfo.type;
      dev.state = pinfo.state;
      dev.fidl_channel = ch;
      dev.events = h;
      memcpy(dev.name, de->d_name, sizeof(dev.name));
      interfaces.push_back(dev);
    }
  }

  if (args.poll_events) {
    poll_events(interfaces);
  }

  return 0;
}
