// Copyright 2015 The Chromium OS 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 "thermald/config_parser.h"

#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/json/json_reader.h"
#include "base/logging.h"
#include "base/strings/string_util.h"
#include "base/values.h"

#include "thermald/configuration.h"
#include "thermald/thermal_zone.h"

using std::make_pair;
using std::string;
using std::unique_ptr;

namespace thermald {

static const int kNoThreshold = -1;

Configuration *ConfigParser::ParseFile(
    const base::FilePath &config_file) {
  string data;
  if (!base::ReadFileToString(config_file, &data)) {
    return nullptr;
  }

  base::Optional<base::Value> root_node(
      base::JSONReader::Read(data, base::JSON_ALLOW_TRAILING_COMMAS));
  if (!root_node) {
    LOG(ERROR) << "Configuration error: Configuration file is invalid";
    return nullptr;
  }

  ConfigParser parser;
  return parser.ParseConfiguration(root_node.value());
}

Configuration *ConfigParser::ParseConfiguration(const base::Value &root_node) {
  if (!root_node.is_dict()) {
    LOG(ERROR) << "Configuration error: Configuration file is invalid";
    return nullptr;
  }

  unique_ptr<Configuration> cfg(new Configuration);
  cfg_ = cfg.get();

  const base::Value *sensors = root_node.FindListKey("sensors");
  if (!sensors) {
    LOG(ERROR) << "Configuration error: Sensor configuration missing";
    return nullptr;
  }

  if (!ProcessSensorConfig(*sensors)) {
    return nullptr;
  }

  const base::Value *thermal_zones = root_node.FindListKey("thermal_zones");
  if (!thermal_zones) {
    LOG(ERROR) << "Configuration error: Thermal zone configuration missing";
    return nullptr;
  }

  if (!ProcessThermalZoneConfig(*thermal_zones)) {
    return nullptr;
  }

  // If uma_metric_prefix section is not present in thermal configuration,
  // then default UMA metric prefix will be "Platform".
  cfg_->uma_metric_prefix = "Platform";
  const base::Value *uma_metric_prefix =
      root_node.FindListKey("uma_metric_prefix");
  if (uma_metric_prefix) {
    if (!ProcessUmaMetricPrefixConfig(*uma_metric_prefix)) {
      return nullptr;
    }
  }

  return cfg.release();
}

bool ConfigParser::ProcessOneThermalState(ThermalZoneCfg *zone_cfg,
                                          const base::Value &state_node,
                                          int index_state) {
  unique_ptr<ThermalStateCfg> state_cfg(new ThermalStateCfg);
  const auto &state_list = state_node.GetList();
  if ((state_list.size() != 3) || !state_list[0].is_int() ||
      !state_list[1].is_list() || !state_list[2].is_dict()) {
    LOG(ERROR) << "Configuration error: State " << index_state
               << " in thermal zone '" << zone_cfg->name << "' is invalid";
    return false;
  }
  state_cfg->id = state_list[0].GetInt();
  const auto &threshold_list = state_list[1].GetList();

  const size_t num_thresholds = threshold_list.size();
  if (((index_state == 0) && (num_thresholds != 0)) ||
      ((index_state != 0) && (num_thresholds != zone_cfg->sensors.size()))) {
    LOG(ERROR) << "Configuration error: Threshold configuration of state "
               << state_cfg->id << " in thermal zone '" << zone_cfg->name
               << "' is invalid";
    return false;
  }

  if (index_state != 0) {
    size_t i = 0;
    for (const auto &thresholds_cfg : threshold_list) {
      if (!thresholds_cfg.is_list()) {
        LOG(ERROR) << "Configuration error: Threshold configuration of state "
                   << state_cfg->id << " in thermal zone '" << zone_cfg->name
                   << "' is invalid";
        return false;
      }

      const auto &thresholds_cfg_list = thresholds_cfg.GetList();
      if ((thresholds_cfg_list.size() != 2) ||
          !thresholds_cfg_list[0].is_int() ||
          !thresholds_cfg_list[1].is_int()) {
        LOG(ERROR) << "Configuration error: Threshold configuration of state "
                   << state_cfg->id << " in thermal zone '" << zone_cfg->name
                   << "' is invalid";
        return false;
      }
      ThermalPointThresholds thresholds;
      thresholds.activation = thresholds_cfg_list[0].GetInt();
      thresholds.bottom = thresholds_cfg_list[1].GetInt();

      if ((thresholds.activation != kNoThreshold) &&
          (thresholds.bottom != kNoThreshold)) {
        thresholds.activation *= 1000;
        thresholds.bottom *= 1000;

        if ((thresholds.activation < thresholds_prev_state_[i].activation) ||
            (thresholds.bottom < thresholds_prev_state_[i].bottom)) {
          LOG(ERROR) << "Configuration error: Configuration of state "
                     << state_cfg->id << " in thermal zone '"
                     << zone_cfg->name << "' is invalid. Thermal states must be"
                     << " ordered by ascending temperature";
          return false;
        }

        thresholds_prev_state_[i] = thresholds;
      } else {
        // Sensor doesn't have thresholds in this thermal state.
        thresholds.activation = kTempInfinite;
        thresholds.bottom = kTemp0K;
      }

      if (thresholds.bottom >= thresholds.activation) {
        LOG(ERROR) << "Configuration error: Threshold configuration of state "
                   << state_cfg->id << " in thermal zone '" << zone_cfg->name
                   << "' is invalid. Bottom treshold must be lower than"
                   << " activation threshold";
        return false;
      }

      state_cfg->thresholds.insert(make_pair(zone_cfg->sensors[i], thresholds));
      i++;
    }
  } else {
    // Set dummy thresholds for first state.

    thresholds_prev_state_.clear();

    for (const string &sensor : zone_cfg->sensors) {
      ThermalPointThresholds thresholds;
      thresholds.activation = kTemp0K;
      thresholds.bottom = kTemp0K;

      state_cfg->thresholds.insert(make_pair(sensor, thresholds));
      thresholds_prev_state_.push_back(thresholds);
    }
  }

  for (const auto &kv : state_list[2].DictItems()) {
    auto value = kv.second.GetIfInt();
    if (!value.has_value()) {
      LOG(ERROR) << "Configuration error: Thermal output configuration "
                 << "of state " << state_cfg->id << " in thermal zone '"
                 << zone_cfg->name << "' is invalid";
      return false;
    }
    ThermalStateOutput output = {kv.first, *value};
    state_cfg->outputs.push_back(output);
  }

  zone_cfg->states.push_back(std::move(state_cfg));

  return true;
}

bool ConfigParser::ProcessOneThermalZone(const base::Value &zone_node,
                                         int index_zone) {
  unique_ptr<ThermalZoneCfg> zone_cfg(new ThermalZoneCfg);

  const auto &zone_list = zone_node.GetList();
  if ((zone_list.size() != 3) || !zone_list[0].is_string() ||
      !zone_list[1].is_list() || !zone_list[2].is_list()) {
    LOG(ERROR) << "Configuration error: Configuration of thermal zone "
               << index_zone << " is invalid";
    return false;
  }
  zone_cfg->name = zone_list[0].GetString();
  const auto &sensors = zone_list[1].GetList();
  const auto &thermal_states = zone_list[2].GetList();

  const size_t num_sensors = sensors.size();
  if (num_sensors == 0) {
    LOG(ERROR) << "Configuration error: Thermal zone '" << zone_cfg->name
               << "' has no sensors";
    return false;
  }

  for (const auto &sensor : sensors) {
    if (!sensor.is_string()) {
      LOG(ERROR) << "Configuration error: Sensor configuration of << "
                 << "thermal zone '" << zone_cfg->name << "' is invalid";
      return false;
    }
    const string& sensor_name = sensor.GetString();

    if (cfg_->sensors.find(sensor_name) == cfg_->sensors.end()) {
      LOG(ERROR) << "Configuration error: Thermal zone '" << zone_cfg->name
                 << "' uses unknown sensor '" << sensor_name << "'";
      return false;
    }

    zone_cfg->sensors.push_back(sensor_name);
  }

  const size_t num_states = thermal_states.size();
  if (num_states < 2) {
    LOG(ERROR) << "Configuration error: Not enough thermal states in "
               << "thermal zone '" << zone_cfg->name << "'";
    return false;
  }

  size_t i = 0;
  for (const auto &state : thermal_states) {
    if (!state.is_list()) {
      LOG(ERROR) << "Configuration error: State " << i << " in thermal zone '"
                 << zone_cfg->name << "' is invalid";
      return false;
    }

    if (!ProcessOneThermalState(zone_cfg.get(), state, i)) {
      return false;
    }
    i++;
  }

  cfg_->zones.insert(make_pair(zone_cfg->name, std::move(zone_cfg)));

  return true;
}

bool ConfigParser::ProcessThermalZoneConfig(const base::Value &thermal_zones) {
  size_t i = 0;
  for (const auto &zone_node : thermal_zones.GetList()) {
    if (!zone_node.is_list()) {
      LOG(ERROR) << "Configuration error: Configuration of thermal zone "
                 << i << " is invalid";
      return false;
    }

    if (!ProcessOneThermalZone(zone_node, i)) {
      return false;
    }
    i++;
  }

  return true;
}

bool ConfigParser::ProcessOneSensor(const base::Value &sensor_node,
                                    int index_sensor) {
  unique_ptr<SensorCfg> sensor_cfg(new SensorCfg);

  const auto &sensor_node_list = sensor_node.GetList();
  if ((sensor_node_list.size() != 4) || !sensor_node_list[0].is_string() ||
      !sensor_node_list[1].is_string() || !sensor_node_list[2].is_list() ||
      !sensor_node_list[3].is_int()) {
    LOG(ERROR) << "Configuration error: Configuration of sensor "
               << index_sensor << " is invalid";
    return false;
  }
  sensor_cfg->name = sensor_node_list[0].GetString();
  const string& sensor_type = sensor_node_list[1].GetString();
  const auto &params = sensor_node_list[2].GetList();
  sensor_cfg->sampling_period = sensor_node_list[3].GetInt();

  if (cfg_->sensors.find(sensor_cfg->name) != cfg_->sensors.end()) {
    LOG(ERROR) << "Configuration error: Sensor '" << sensor_cfg->name
               << "' is defined more than once";
    return false;
  }

  if (sensor_type == "ath10k") {
    if ((params.size() != 1) || !params[0].is_string()) {
      LOG(ERROR) << "Configuration error: Sensor '" << sensor_cfg->name
                 << "' has invalid parameters";
      return false;
    }

    const string& wlan_interface = params[0].GetString();
    base::strlcpy(sensor_cfg->ath10k_sensor.wlan_interface,
                  wlan_interface.c_str(),
                  sizeof(sensor_cfg->ath10k_sensor.wlan_interface));
    sensor_cfg->type = kAth10kSensor;
  } else if (sensor_type == "hwmon") {
    if ((params.size() != 2) || !params[0].is_int() || !params[1].is_int()) {
      LOG(ERROR) << "Configuration error: Sensor '" << sensor_cfg->name
                 << "' has invalid parameters";
      return false;
    }

    sensor_cfg->hwmon_sensor.chip_id = params[0].GetInt();
    sensor_cfg->hwmon_sensor.sensor_id = params[1].GetInt();
    sensor_cfg->type = kHwmonSensor;
  } else if (sensor_type == "thermal_zone") {
    if ((params.size() != 1) || !params[0].is_int()) {
      LOG(ERROR) << "Configuration error: Sensor '" << sensor_cfg->name
                 << "' has invalid parameters";
      return false;
    }

    sensor_cfg->thermal_zone_sensor.zone_id = params[0].GetInt();
    sensor_cfg->type = kThermalZoneSensor;
  } else if (sensor_type == "iio") {
    if ((params.size() != 2) || !params[0].is_string() ||
        !params[1].is_string()) {
      LOG(ERROR) << "Configuration error: Sensor '" << sensor_cfg->name
                 << "' has invalid parameters";
      return false;
    }

    base::strlcpy(sensor_cfg->iio_sensor.iio_device_name,
                  params[0].GetString().c_str(),
                  sizeof(sensor_cfg->iio_sensor.iio_device_name));
    base::strlcpy(sensor_cfg->iio_sensor.iio_sensor_name,
                  params[1].GetString().c_str(),
                  sizeof(sensor_cfg->iio_sensor.iio_sensor_name));
    sensor_cfg->type = kIioSensor;
  } else if (sensor_type == "fake") {
    if ((params.size() != 1) || !params[0].is_string()) {
      LOG(ERROR) << "Configuration error: Sensor '" << sensor_cfg->name
                 << "' has invalid parameters";
      return false;
    }

    // This might cause a memory leak, but as this is a fake sensor it is
    // preferrable over reserving memory for the path in SensorCfg
    sensor_cfg->fake_sensor.fake_data_file =
        strdup(params[0].GetString().c_str());

    sensor_cfg->type = kFakeSensor;
  } else {
    LOG(ERROR) << "Configuration error: Invalid sensor type '"
               << sensor_type << "'";
    return false;
  }

  cfg_->sensors.insert(make_pair(sensor_cfg->name, std::move(sensor_cfg)));

  return true;
}

bool ConfigParser::ProcessSensorConfig(const base::Value &sensors) {
  size_t i = 0;
  for (const auto &sensor_node : sensors.GetList()) {
    if (!sensor_node.is_list()) {
      LOG(ERROR) << "Configuration error: Configuration of sensor "
                 << i << " is invalid";
      return false;
    }

    if (!ProcessOneSensor(sensor_node, i)) {
      return false;
    }
    i++;
  }

  return true;
}

bool ConfigParser::ProcessUmaMetricPrefixConfig(
    const base::Value &uma_metric_prefix) {
  const auto &prefix_list = uma_metric_prefix.GetList();
  if (prefix_list.size() != 1) {
    LOG(ERROR) << "Configuration error: Configuration of uma_metric_prefix "
               << "is invalid";
    return false;
  }

  if (!prefix_list[0].is_list()) {
    LOG(ERROR) << "Configuration error: uma_metric_prefix has"
               << " invalid parameters";
    return false;
  }
  const auto &params = prefix_list[0].GetList();

  if (!params[0].is_string()) {
    LOG(ERROR) << "Configuration error: Configuration of uma_metric_prefix"
               << " is invalid";
    return false;
  }
  cfg_->uma_metric_prefix = params[0].GetString();

  return true;
}

}  // namespace thermald
