#include "monolog.h"
#include "zori.h"
#include "zori_widget.h"
#include "zori_caption.h"
#include "zori_button.h"

struct zori_button * zori_widget_to_button(struct zori_widget * widget) {
  if (!zori_widget_is_type(widget, ZORI_WIDGET_TYPE_BUTTON)) return NULL;
  return ZORI_CONTAINER_OF(widget, struct zori_button, widget);
}


/** Handles a mouse axis event and pass it on.  */
int zori_button_on_mouse_axes(union zori_event * event) { 
    struct zori_widget * widget = event->any.widget;
    struct zori_button * button = zori_widget_to_button(widget);
    float x = event->sys.ev->mouse.x;
    float y = event->sys.ev->mouse.y;
    if (zori_xy_inside_widget_p(widget, x, y)) {
      zori_widget_hover_(widget, TRUE);
    } else {
      zori_widget_hover_(widget, FALSE);
    }
    
    return ZORI_HANDLE_PASS;
}

/** Handles a mouse click event and pass it on.  */
int zori_button_on_mouse_click(union zori_event * event) { 
    struct zori_widget * widget = event->any.widget;
    struct zori_button * button = zori_widget_to_button(widget);
    float x = event->sys.ev->mouse.x;
    float y = event->sys.ev->mouse.y;
    if (zori_xy_inside_widget_p(widget, x, y)) {
      widget->result = widget->id;
      LOG_NOTE("Button %d clicked: %d, result %d.\n", widget->id, widget->result);
      return zori_widget_raise_action_event(widget);
    }
    return ZORI_HANDLE_PASS;
}


void zori_draw_button(struct zori_button * button) {
  float x, y, w, h;
  struct zori_style * style = &button->widget.style; 
  x = rebox_x(&button->widget.inner);
  y = rebox_y(&button->widget.inner);
  w = rebox_w(&button->widget.inner);
  h = rebox_h(&button->widget.inner);
  
  zori_widget_draw_background(&button->widget);
  zori_caption_draw(&button->caption, &button->widget.inner, &button->widget.style);  
};
 
int zori_button_on_draw(union zori_event * event) {
  struct zori_button * button = zori_widget_to_button(event->any.widget);
  zori_draw_button(button);
  return ZORI_HANDLE_PASS;
}


struct zori_handler zori_button_handlers[] = {
  { ZORI_SYSTEM_EVENT_MOUSE_BUTTON_DOWN , zori_button_on_mouse_click   , NULL },
  { ZORI_SYSTEM_EVENT_MOUSE_AXES        , zori_button_on_mouse_axes    , NULL },
  { ZORI_EVENT_DRAW                     , zori_button_on_draw          , NULL },
  { -1, NULL, NULL }
};


struct zori_button * 
zori_button_text_(struct zori_button * button, zori_string * text) {
  if (button) {
    zori_caption_set(&button->caption, text);
  } 
  return button;
}

void zori_button_destroy(struct zori_widget * widget) {
  struct zori_button * button = zori_widget_to_button(widget);
  if (button) {
    zori_caption_done(&button->caption);
  }
}

struct zori_button * 
zori_button_init(struct zori_button * button,const char * text) {
  if (button) {
    zori_caption_init(&button->caption, text);
    button->widget.destroy = zori_button_destroy;
  }
  return button;
}

struct zori_button * zori_button_new(zori_id id, zori_id parent_id, 
  zori_box * box, const char * text) {
  struct zori_button * button = NULL;
  button = calloc(1, sizeof(*button));
  if (!button) return NULL;
  zori_widget_initall(&button->widget, ZORI_WIDGET_TYPE_BUTTON, id, zori_get_widget(parent_id), 
                      box, NULL, ZORI_ARRAY_AND_AMOUNT(zori_button_handlers)); 
  if (!zori_button_init(button, text)) {
    free(button);
    button = NULL;
  }
  zori_widget_hover_(&button->widget, 0);
  
  return button;
}


zori_id zori_new_button(zori_id id, zori_id parent, zori_box * box, const char * text) {
  struct zori_button * button = zori_button_new(id, parent, box, text);
  if (!button) return ZORI_ID_ENOMEM;
  return button->widget.id;
}


