#include "modules/image.hpp"

waybar::modules::Image::Image(const std::string& id, const Json::Value& config)
    : AModule(config, "image", id), box_(Gtk::ORIENTATION_HORIZONTAL, 0) {
  box_.pack_start(image_);
  box_.set_name("image");
  if (!id.empty()) {
    box_.get_style_context()->add_class(id);
  }
  box_.get_style_context()->add_class(MODULE_CLASS);
  event_box_.add(box_);

  dp.emit();

  size_ = config["size"].asInt();

  const auto once = std::chrono::milliseconds::max();
  if (!config_.isMember("interval") || config_["interval"].isNull() ||
      config_["interval"] == "once") {
    interval_ = once;
  } else if (config_["interval"].isNumeric()) {
    const auto interval_seconds = config_["interval"].asDouble();
    if (interval_seconds <= 0) {
      interval_ = once;
    } else {
      interval_ =
          std::chrono::milliseconds(std::max(1L,  // Minimum 1ms due to millisecond precision
                                             static_cast<long>(interval_seconds * 1000)));
    }
  } else {
    interval_ = once;
  }

  if (size_ == 0) {
    size_ = 16;
  }

  delayWorker();
}

void waybar::modules::Image::delayWorker() {
  thread_ = [this] {
    dp.emit();
    thread_.sleep_for(interval_);
  };
}

void waybar::modules::Image::refresh(int sig) {
  if (config_["signal"].isInt() && sig == SIGRTMIN + config_["signal"].asInt()) {
    thread_.wake_up();
  }
}

auto waybar::modules::Image::update() -> void {
  if (config_["path"].isString()) {
    path_ = config_["path"].asString();
  } else if (config_["exec"].isString()) {
    output_ = util::command::exec(config_["exec"].asString(), "");
    parseOutputRaw();
  } else {
    path_ = "";
  }

  if (Glib::file_test(path_, Glib::FILE_TEST_EXISTS)) {
    Glib::RefPtr<Gdk::Pixbuf> pixbuf;

    int scaled_icon_size = size_ * image_.get_scale_factor();
    pixbuf = Gdk::Pixbuf::create_from_file(path_, scaled_icon_size, scaled_icon_size);

    auto surface = Gdk::Cairo::create_surface_from_pixbuf(pixbuf, image_.get_scale_factor(),
                                                          image_.get_window());
    image_.set(surface);
    image_.show();

    if (tooltipEnabled() && !tooltip_.empty()) {
      if (box_.get_tooltip_markup() != tooltip_) {
        box_.set_tooltip_markup(tooltip_);
      }
    }

    box_.get_style_context()->remove_class("empty");
  } else {
    image_.clear();
    image_.hide();
    box_.get_style_context()->add_class("empty");
  }

  AModule::update();
}

void waybar::modules::Image::parseOutputRaw() {
  std::istringstream output(output_.out);
  std::string line;
  int i = 0;
  while (getline(output, line)) {
    if (i == 0) {
      path_ = line;
    } else if (i == 1) {
      tooltip_ = line;
    } else {
      break;
    }
    i++;
  }
}
