// Copyright 2015 The Weave 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 "examples/daemon/common/daemon.h"

#include <weave/device.h>
#include <weave/provider/task_runner.h>

#include <base/bind.h>
#include <base/memory/weak_ptr.h>

namespace {
// Time for sensor temperature to match setting temperature
const double kWarmUpTime = 60.0;
// Oven max temp
const double kMaxTemp = 300.0;
// Oven min temp
const double kMinTemp = 20.0;

const char kTraits[] = R"({
  "temperatureSetting": {
    "commands": {
      "setConfig": {
        "minimalRole": "user",
        "parameters": {
          "units": {
            "type": "string"
          },
          "tempSetting": {
            "type": "number"
          }
        },
        "errors": ["tempOutOfRange", "unsupportedUnits"]
      }
    },
    "state": {
      "supportedUnits": {
        "type": "array",
        "items": {
          "type": "string",
          "enum": [ "celsius", "fahrenheit", "kelvin" ]
        },
        "minItems": 1,
        "uniqueItems": true,
        "isRequired": true
      },
      "units": {
        "type": "string",
        "enum": [ "celsius", "fahrenheit", "kelvin" ],
        "isRequired": true
      },
      "tempSetting": {
        "type": "number",
        "isRequired": true
      },
      "maxTempSetting": {
        "type": "number",
        "isRequired": true
      },
      "minTempSetting": {
        "type": "number",
        "isRequired": true
      }
    }
  },
  "temperatureSensor": {
    "commands": {
      "setConfig": {
        "minimalRole": "user",
        "parameters": {
          "units": {
            "type": "string"
          }
        },
        "errors": ["unsupportedUnits"]
      }
    },
    "state": {
      "supportedUnits": {
        "type": "array",
        "items": {
          "type": "string",
          "enum": [
            "celsius",
            "fahrenheit",
            "kelvin"
          ]
        },
        "minItems": 1,
        "uniqueItems": true,
        "isRequired": true
      },
      "units": {
        "type": "string",
        "enum": [ "celsius", "fahrenheit", "kelvin" ],
        "isRequired": true
      },
      "value": {
        "type": "number",
        "isRequired": true
      }
    }
  },
  "brightness": {
    "commands": {
      "setConfig": {
        "minimalRole": "user",
        "parameters": {
          "brightness": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100
          }
        }
      }
    },
    "state": {
      "brightness": {
        "type": "integer",
        "isRequired": true,
        "minimum": 0,
        "maximum": 100
      }
    }
  }
})";

const char kComponent[] = "oven";
}  // anonymous namespace

// OvenHandler is a virtual oven example
// It implements the following commands from traits:
// - temperatureSetting: sets the temperature for the oven
// - brightness: sets the brightness of the oven light
// It exposes the following states from traits:
// - temperatureSetting: temperature setting for the oven
// - temperatureSensor: current oven temperature
// - brightness: current oven brightness
class OvenHandler {
 public:
  OvenHandler(weave::provider::TaskRunner* task_runner)
      : task_runner_{task_runner} {}

  void Register(weave::Device* device) {
    device_ = device;

    device->AddTraitDefinitionsFromJson(kTraits);
    CHECK(device->AddComponent(
        kComponent, {"temperatureSetting", "temperatureSensor", "brightness"},
        nullptr));

    UpdateOvenState();

    device->AddCommandHandler(kComponent, "temperatureSetting.setConfig",
                              base::Bind(&OvenHandler::OnSetTempCommand,
                                         weak_ptr_factory_.GetWeakPtr()));

    device->AddCommandHandler(kComponent, "brightness.setConfig",
                              base::Bind(&OvenHandler::OnSetBrightnessCommand,
                                         weak_ptr_factory_.GetWeakPtr()));
  }

 private:
  void OnSetTempCommand(const std::weak_ptr<weave::Command>& command) {
    auto cmd = command.lock();
    if (!cmd)
      return;
    LOG(INFO) << "received command: " << cmd->GetName();

    const auto& params = cmd->GetParameters();
    std::string units;
    double temp;

    if (params.GetString("units", &units) &&
        params.GetDouble("tempSetting", &temp)) {
      units_ = units;
      target_temperature_ = temp;

      UpdateOvenState();

      cmd->Complete({}, nullptr);
      LOG(INFO) << cmd->GetName() << " updated oven, matching temp";

      if (target_temperature_ != current_temperature_ && !is_match_ticking_) {
        double tickIncrement =
            ((target_temperature_ - current_temperature_) / kWarmUpTime);
        DoTick(tickIncrement);
      }
      return;
    }

    weave::ErrorPtr error;
    weave::Error::AddTo(&error, FROM_HERE, "invalid_parameter_value",
                        "Invalid parameters");
    cmd->Abort(error.get(), nullptr);
  }

  void OnSetBrightnessCommand(const std::weak_ptr<weave::Command>& command) {
    auto cmd = command.lock();
    if (!cmd)
      return;
    LOG(INFO) << "received command: " << cmd->GetName();

    const auto& params = cmd->GetParameters();

    int brightness;
    if (params.GetInteger("brightness", &brightness)) {
      brightness_ = brightness;

      UpdateOvenState();

      cmd->Complete({}, nullptr);
      return;
    }

    weave::ErrorPtr error;
    weave::Error::AddTo(&error, FROM_HERE, "invalid_parameter_value",
                        "Invalid parameters");
    cmd->Abort(error.get(), nullptr);
  }

  void UpdateOvenState() {
    base::DictionaryValue state;
    base::ListValue supportedUnits;
    supportedUnits.AppendStrings({"celsius"});

    state.SetString("temperatureSensor.units", units_);
    state.SetDouble("temperatureSensor.value", current_temperature_);
    state.Set("temperatureSensor.supportedUnits",
              supportedUnits.CreateDeepCopy());

    state.SetString("temperatureSetting.units", units_);
    state.SetDouble("temperatureSetting.tempSetting", target_temperature_);
    state.Set("temperatureSetting.supportedUnits",
              supportedUnits.CreateDeepCopy());
    state.SetDouble("temperatureSetting.maxTempSetting", kMaxTemp);
    state.SetDouble("temperatureSetting.minTempSetting", kMinTemp);

    state.SetInteger("brightness.brightness", brightness_);

    device_->SetStateProperties(kComponent, state, nullptr);
  }

  void DoTick(double tickIncrement) {
    LOG(INFO) << "Oven matching temp tick";

    if (std::fabs(target_temperature_ - current_temperature_) >=
        tickIncrement) {
      is_match_ticking_ = true;
      current_temperature_ += tickIncrement;
      UpdateOvenState();
      task_runner_->PostDelayedTask(
          FROM_HERE, base::Bind(&OvenHandler::DoTick,
                                weak_ptr_factory_.GetWeakPtr(), tickIncrement),
          base::TimeDelta::FromSeconds(1));
      return;
    }

    is_match_ticking_ = false;
    current_temperature_ = target_temperature_;
    UpdateOvenState();

    LOG(INFO) << "Oven temp matched";
  }

  weave::Device* device_{nullptr};
  weave::provider::TaskRunner* task_runner_{nullptr};

  std::string units_ = "celsius";
  double target_temperature_ = 0.0;
  double current_temperature_ = 0.0;
  int brightness_ = 0;
  bool is_match_ticking_ = false;

  base::WeakPtrFactory<OvenHandler> weak_ptr_factory_{this};
};

int main(int argc, char** argv) {
  Daemon::Options opts;
  if (!opts.Parse(argc, argv)) {
    Daemon::Options::ShowUsage(argv[0]);
    return 1;
  }
  Daemon daemon{opts};
  OvenHandler handler{daemon.GetTaskRunner()};
  handler.Register(daemon.GetDevice());
  daemon.Run();
  return 0;
}
