// 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;
}
