#include "QtWidgets/QButtonGroup/qbuttongroup_wrap.h"

#include <QDebug>
#include <QWidget>

#include "Extras/Utils/nutils.h"
#include "QtCore/QObject/qobject_wrap.h"
#include "QtGui/QIcon/qicon_wrap.h"
#include "QtWidgets/QMenu/qmenu_wrap.h"
#include "QtWidgets/QWidget/qwidget_wrap.h"

Napi::FunctionReference QButtonGroupWrap::constructor;

Napi::Object QButtonGroupWrap::init(Napi::Env env, Napi::Object exports) {
  Napi::HandleScope scope(env);
  char CLASSNAME[] = "QButtonGroup";
  Napi::Function func = DefineClass(
      env, CLASSNAME,
      {InstanceMethod("addButton", &QButtonGroupWrap::addButton),
       InstanceMethod("checkedId", &QButtonGroupWrap::checkedId),
       InstanceMethod("setId", &QButtonGroupWrap::setId),
       InstanceMethod("removeButton", &QButtonGroupWrap::removeButton),
       InstanceMethod("id", &QButtonGroupWrap::id),
       InstanceMethod("checkedButton", &QButtonGroupWrap::checkedButton),
       InstanceMethod("buttons", &QButtonGroupWrap::buttons),
       InstanceMethod("button", &QButtonGroupWrap::button),
       QOBJECT_WRAPPED_METHODS_EXPORT_DEFINE(QButtonGroupWrap)});
  constructor = Napi::Persistent(func);
  exports.Set(CLASSNAME, func);
  QOBJECT_REGISTER_WRAPPER(QButtonGroup, QButtonGroupWrap);
  return exports;
}

QButtonGroup* QButtonGroupWrap::getInternalInstance() { return this->instance; }

QButtonGroupWrap::QButtonGroupWrap(const Napi::CallbackInfo& info)
    : Napi::ObjectWrap<QButtonGroupWrap>(info) {
  Napi::Env env = info.Env();
  size_t argCount = info.Length();
  if (argCount == 0) {
    // --- Construct a new instance
    this->instance = new NButtonGroup();
  } else if (argCount == 1) {
    if (info[0].IsExternal()) {
      // --- Wrap a given C++ instance
      this->instance = info[0].As<Napi::External<QButtonGroup>>().Data();
    } else {
      Napi::Object parentObject = info[0].As<Napi::Object>();
      NodeWidgetWrap* parentWidgetWrap =
          Napi::ObjectWrap<NodeWidgetWrap>::Unwrap(parentObject);
      this->instance =
          new NButtonGroup(parentWidgetWrap->getInternalInstance());
    }
  } else {
    Napi::TypeError::New(
        env,
        "NodeGui: QButtonGroupWrap: Wrong number of arguments to constructor")
        .ThrowAsJavaScriptException();
  }
  this->rawData = extrautils::configureQObject(this->getInternalInstance());
}

QButtonGroupWrap::~QButtonGroupWrap() {
  extrautils::safeDelete(this->instance);
}

Napi::Value QButtonGroupWrap::addButton(const Napi::CallbackInfo& info) {
  Napi::Env env = info.Env();
  Napi::Object buttonObject = info[0].As<Napi::Object>();
  QObjectWrap* objectWrap = Napi::ObjectWrap<QObjectWrap>::Unwrap(buttonObject);
  QAbstractButton* button =
      qobject_cast<QAbstractButton*>(objectWrap->getInternalInstance());
  Napi::Number id = info[1].As<Napi::Number>();

  this->instance->addButton(button, id.Int32Value());
  return env.Null();
}
Napi::Value QButtonGroupWrap::removeButton(const Napi::CallbackInfo& info) {
  Napi::Env env = info.Env();
  Napi::Object buttonObject = info[0].As<Napi::Object>();
  QObjectWrap* objectWrap = Napi::ObjectWrap<QObjectWrap>::Unwrap(buttonObject);
  QAbstractButton* button =
      qobject_cast<QAbstractButton*>(objectWrap->getInternalInstance());
  this->instance->removeButton(button);
  return env.Null();
}
Napi::Value QButtonGroupWrap::checkedId(const Napi::CallbackInfo& info) {
  Napi::Env env = info.Env();
  int value = static_cast<int>(this->instance->checkedId());
  return Napi::Number::From(env, value);
}
Napi::Value QButtonGroupWrap::checkedButton(const Napi::CallbackInfo& info) {
  Napi::Env env = info.Env();
  auto value = Napi::External<QAbstractButton>::New(
      env, this->instance->checkedButton());
  return Napi::Value::From(env, value);
}
Napi::Value QButtonGroupWrap::id(const Napi::CallbackInfo& info) {
  Napi::Env env = info.Env();
  Napi::Object buttonObject = info[0].As<Napi::Object>();
  QObjectWrap* objectWrap = Napi::ObjectWrap<QObjectWrap>::Unwrap(buttonObject);
  QAbstractButton* button =
      qobject_cast<QAbstractButton*>(objectWrap->getInternalInstance());
  int value = static_cast<int>(this->instance->id(button));
  return Napi::Number::From(env, value);
}
Napi::Value QButtonGroupWrap::setId(const Napi::CallbackInfo& info) {
  Napi::Env env = info.Env();
  Napi::Object buttonObject = info[0].As<Napi::Object>();
  QObjectWrap* objectWrap = Napi::ObjectWrap<QObjectWrap>::Unwrap(buttonObject);
  QAbstractButton* button =
      qobject_cast<QAbstractButton*>(objectWrap->getInternalInstance());
  Napi::Number id = info[1].As<Napi::Number>();

  this->instance->setId(button, id.Int32Value());
  return env.Null();
}
Napi::Value QButtonGroupWrap::buttons(const Napi::CallbackInfo& info) {
  Napi::Env env = info.Env();

  QList<QAbstractButton*> items = this->instance->buttons();
  Napi::Array napiItems = Napi::Array::New(env, items.size());
  for (int i = 0; i < items.size(); i++) {
    QAbstractButton* item = items[i];
    auto value = Napi::External<QAbstractButton>::New(env, item);
    napiItems[i] = value;
  }

  return napiItems;
}
Napi::Value QButtonGroupWrap::button(const Napi::CallbackInfo& info) {
  Napi::Env env = info.Env();
  Napi::Number id = info[0].As<Napi::Number>();

  auto value =
      Napi::External<QAbstractButton>::New(env, this->instance->button(id));
  return Napi::Value::From(env, value);
}