#pragma once

#include <array>
#include <stdexcept>

#include "../common.h"
#include "color_night_light.h"
#include "color_off.h"
#include "color_rgb_light.h"
#include "color_white_light.h"
#include "gpio_outputs.h"

namespace esphome {
namespace xiaomi {
namespace bslamp2 {

/**
 * This class translates LightColorValues into GPIO duty cycles that
 * can be used for representing a requested light color on the
 * physical device.
 *
 * The code handles all known light modes for the device:
 *
 * - off: the light is off
 * - night light: based on RGB or white mode + lowest possible brightness
 * - white light: based on color temperature + brightness
 * - RGB light: based on RGB values + brightness
 */
class ColorInstantHandler : public GPIOOutputs {
 public:
  bool set_light_color_values(light::LightColorValues v) {
    // The actual implementation of the various light modes is in
    // separated targeted classes. These classes are called here
    // in a chain of command-like pattern, to let the first one
    // that can handle the light settings do the honours.
    if (off_light_->set_light_color_values(v))
      off_light_->copy_to(this);
    else if (night_light_->set_light_color_values(v))
      night_light_->copy_to(this);
    else if (white_light_->set_light_color_values(v))
      white_light_->copy_to(this);
    else if (rgb_light_->set_light_color_values(v))
      rgb_light_->copy_to(this);
    else {
      ESP_LOGE(TAG, "Light color error: (None of the GPIOOutputs classes handles the requested light state; defaulting to 'off'");
      off_light_->copy_to(this);
    }

    return true;
  }

 protected:
  GPIOOutputs *off_light_ = new ColorOff();
  GPIOOutputs *rgb_light_ = new ColorRGBLight();
  GPIOOutputs *white_light_ = new ColorWhiteLight();
  GPIOOutputs *night_light_ = new ColorNightLight();
};

}  // namespace bslamp2
}  // namespace xiaomi
}  // namespace esphome
