// Licensed GNU LGPL v2.1 or later: http://www.gnu.org/licenses/lgpl-2.1.html

#ifndef SPECTMORPH_CONTROL_VIEW_HH
#define SPECTMORPH_CONTROL_VIEW_HH

#include "smcomboboxoperator.hh"

namespace SpectMorph
{

class ControlView : public SignalReceiver
{
  struct Entry
  {
    MorphOperator::ControlType ctype;
    std::string                text;
  };
  const std::vector<Entry> entries =
    {
      { MorphOperator::CONTROL_GUI, "Gui Slider"},
      { MorphOperator::CONTROL_SIGNAL_1, "Control Signal #1"},
      { MorphOperator::CONTROL_SIGNAL_2, "Control Signal #2"},
      { MorphOperator::CONTROL_SIGNAL_3, "Control Signal #3"},
      { MorphOperator::CONTROL_SIGNAL_4, "Control Signal #4"},
      { MorphOperator::CONTROL_VELOCITY, "Velocity"}
    };
  ComboBoxOperator *control_combobox = nullptr;
public:
  ComboBoxOperator *
  create_combobox (Widget *parent, MorphOperator *op, MorphOperator::ControlType initial_type, MorphOperator *initial_op, bool gui_slider_ok = true)
  {
    auto control_operator_filter = ComboBoxOperator::make_filter (op, MorphOperator::OUTPUT_CONTROL);
    control_combobox = new ComboBoxOperator (parent, op->morph_plan(), control_operator_filter);

    for (auto entry : entries)
      {
        if (entry.ctype != MorphOperator::CONTROL_GUI || gui_slider_ok)
          {
            control_combobox->add_str_choice (entry.text);
          }
        if (entry.ctype == initial_type)
          control_combobox->set_active_str_choice (entry.text);
      }
    if (initial_type == MorphOperator::CONTROL_OP)
      control_combobox->set_active (initial_op);
    control_combobox->set_none_ok (false);

    connect (control_combobox->signal_item_changed, [this]() { signal_control_changed(); });
    return control_combobox;
  }
  MorphOperator *
  op() const
  {
    return control_combobox->active();
  }
  MorphOperator::ControlType
  control_type()
  {
    if (control_combobox->active())
      return MorphOperator::CONTROL_OP;

    std::string active_text = control_combobox->active_str_choice();
    for (auto entry : entries)
      {
        if (entry.text == active_text)
          return entry.ctype;
      }
    /* in principle this cannot be reached but we want to fail gracefully */
    return MorphOperator::CONTROL_GUI;
  }
  void
  update_control_type_and_op (MorphOperator::ControlType type, MorphOperator *op)
  {
    if (type == MorphOperator::CONTROL_OP)
      control_combobox->set_active (op);
    else
      {
        for (auto entry : entries)
          {
            if (entry.ctype == type)
              control_combobox->set_active_str_choice (entry.text);
          }
      }
  }
  Signal<> signal_control_changed;
};

}

#endif
