// 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"
          }
        }
      }
    },
    "state": {
      "supportedUnits": {
        "type": "array",
        "items": {
          "type": "string",
          "enum": [
            "celsius",
            "fahrenheit",
            "kelvin"
          ]
        }
      },
      "units": {
        "type": "string"
      },
      "tempSetting": {
        "type": "number"
      },
      "maxTempSetting": {
        "type": "number"
      },
      "minTempSetting": {
        "type": "number"
      }
    }
  },
  "temperatureSensor": {
    "state": {
      "supportedUnits": {
        "type": "array",
        "items": {
          "type": "string",
          "enum": [
            "celsius",
            "fahrenheit",
            "kelvin"
          ]
        }
      },
      "units": {
        "type": "string"
      },
      "value": {
        "type": "number"
      }
    }
  },
  "brightness": {
    "commands": {
      "setConfig": {
        "minimalRole": "user",
        "parameters": {
          "brightness": {
            "type": "integer",
            "minimum": 0,
            "maximum": 100
          }
        }
      }
    },
    "state": {
      "brightness": {
        "type": "number"
      }
    }
  }
})";

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, "example", "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, "example", "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.DeepCopy());

    state.SetString("temperatureSetting.units", units_);
    state.SetDouble("temperatureSetting.tempSetting", target_temperature_);
    state.Set("temperatureSetting.supportedUnits", supportedUnits.DeepCopy());
    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;
}
