/* c-basic-offset: 2; tab-width: 2; indent-tabs-mode: nil
 * vi: set shiftwidth=2 tabstop=2 expandtab:
 * :indentSize=2:tabSize=2:noTabs=true:
 */

#include "GameObject.h"

/**
 * This file, as the rest of the project is under MIT license.
 * see http://opensource.org/licenses/MIT
 *
 * Author Gustav Hartvigsson <gustav.hartvigsson _at_ gmail.com> 2014
 */

void _game_object_private_set_visible (GameObject * self , bool visible);
bool _game_object_private_get_visible (GameObject * self);

void game_object_class_initialize (GameObjectClass *    klass,
                             NewFunc                    new_func,
                             FreeFunc                   free_func,
                             ToStringFunc               to_string_func,
                             GameObjectCallbackHandlerFunc
                                                          callback_handler_func,
                             GameObjectDrawFunc         draw_func,
                             GameObjectSetCallbackFunc  set_callback_func,
                             GameObjectMoveFunc         move_func,
                             GameObjectSetMovementDeltaFunc
                                                        set_movement_delta_func,
                             GameObjectGetBoundingBoxFunc
                                                        get_bounding_box_func,
                             GameObjectGetIsAliveFunc   get_is_alive_func,
                             GameObjectGetIsCollideFunc get_is_collide_func,
                             GameObjectSetVisibleFunc   set_visible_func,
                             GameObjectGetVisibleFunc   get_visible_func) {
  
  /* First things first, we need to initialise the Object base class. */
  ObjectClass * objkls = (ObjectClass *) klass;
  object_class_initialize (objkls,  new_func, free_func, to_string_func);
  
  /* Now we add the methods to the GameObjectClass */
  klass->callback_handler_func = callback_handler_func;
  klass->set_callback_func = set_callback_func;
  klass->draw_func = draw_func;
  klass->move_func = move_func;
  klass->set_movement_delta_func = set_movement_delta_func;
  klass->get_bounding_box_func = get_bounding_box_func;
  klass->get_is_alive_func = get_is_alive_func;
  klass->get_is_collide_func = get_is_collide_func;
  
  if (set_visible_func == NULL) {
    klass->set_visible_func =  _game_object_private_set_visible;
  } else {
    klass->set_visible_func = set_visible_func;
  }
  
  if (get_visible_func == NULL) {
    klass->get_visible_func =  _game_object_private_get_visible;
  } else {
    klass->get_visible_func = get_visible_func;
  }
  
  /* We are done. */
}

void game_object_draw (GameObject * self, SDL_Renderer * renderer) {
  Object * obj = (Object *) self;
  GameObjectClass * klass = (GameObjectClass *) obj->klass;
  GameObjectDrawFunc draw_func = klass->draw_func;
  draw_func (self, renderer);
}

void game_object_set_movment_delta (GameObject * self, int delta_x,
                                    int delta_y, uint32_t delta_time) {
  Object * obj = (Object *) self;
  GameObjectClass * klass = (GameObjectClass *) obj->klass;
  GameObjectSetMovementDeltaFunc set_movement_delta_func
                                         = klass->set_movement_delta_func;
  set_movement_delta_func (self, delta_x, delta_y, delta_time);
}

bool game_object_get_is_alive (GameObject * self) {
  Object * obj = (Object *) self;
  GameObjectClass * klass = (GameObjectClass *) obj->klass;
  GameObjectGetIsAliveFunc is_alive = klass->get_is_alive_func;
  bool ret = is_alive (self);
  return ret;
}

void game_object_set_callback (GameObject * self, char * name,
                               GameObjectCallbackFunc callback_func,
                               _pointer data) {
  Object * obj = (Object *) self;
  GameObjectClass * klass = (GameObjectClass *) obj->klass;
  GameObjectSetCallbackFunc set_callback_func = klass->set_callback_func;
  set_callback_func (self, name, callback_func, data);
}

void game_object_do_callback (GameObject * self, char * name) {
  Object * obj = (Object *) self;
  GameObjectClass * klass = (GameObjectClass *) obj->klass;
  GameObjectCallbackHandlerFunc do_callback_func = klass->callback_handler_func;
  do_callback_func (self, name);
}

bool game_object_get_is_collide (GameObject * self, GameObject * other) {
  Object * obj = (Object *) self;
  GameObjectClass * klass = (GameObjectClass *) obj->klass;
  GameObjectGetIsCollideFunc s_is_collide = klass->get_is_collide_func;
  bool ret = s_is_collide (self, other);
  return ret;
}

void game_object_set_visible (GameObject * self, bool visible) {
  Object * obj = (Object *) self;
  GameObjectClass * klass = (GameObjectClass *) obj->klass;
  GameObjectSetVisibleFunc set_visible_func = klass->set_visible_func;
  set_visible_func (self, visible);
}

bool game_object_get_visible (GameObject * self) {
  Object * obj = (Object *) self;
  GameObjectClass * klass = (GameObjectClass *) obj->klass;
  GameObjectGetVisibleFunc get_visible_func = klass->get_visible_func;
  return get_visible_func (self);
}

#if 0
/******************************************************************************/


void game_object_set_draw_func (GameObject * self,
                                GameObjectDrawFunc draw_func) {
  Object * obj = (Object *) self;
  GameObjectClass * klass = (GameObjectClass *) obj->klass;
  klass->draw_func = draw_func;
}

void game_object_set_callback_handler_func (GameObject * self,
                          GameObjectCallbackHandlerFunc callback_handler_func) {
  Object * obj = (Object *) self;
  GameObjectClass * klass = (GameObjectClass *) obj->klass;
  klass->callback_handler_func = callback_handler_func;
}

void game_object_set_set_callback_func (GameObject * self,
                                  GameObjectSetCallbackFunc set_callback_func) {
  Object * obj = (Object *) self;
  GameObjectClass * klass = (GameObjectClass *) obj->klass;
  klass->set_callback_func = set_callback_func;
}

void game_object_set_move_func (GameObject * self,
                                GameObjectMoveFunc move_func) {
  Object * obj = (Object *) self;
  GameObjectClass * klass = (GameObjectClass *) obj->klass;
  klass->move_func = move_func;
}

void game_object_set_set_move_delta_func (GameObject * self,
                       GameObjectSetMovementDeltaFunc set_movement_delta_func) {
  Object * obj = (Object *) self;
  GameObjectClass * klass = (GameObjectClass *) obj->klass;
  klass->set_movement_delta_func = set_movement_delta_func;
}

void game_object_set_get_bounding_box_func (GameObject * self,
                           GameObjectGetBoundingBoxFunc get_bounding_box_func) {
  Object * obj = (Object *) self;
  GameObjectClass * klass = (GameObjectClass *) obj->klass;
  klass->get_bounding_box_func = get_bounding_box_func;
}

void game_object_set_get_is_alive_func (GameObject * self,
                                   GameObjectGetIsAliveFunc get_is_alive_func) {
  Object * obj = (Object *) self;
  GameObjectClass * klass = (GameObjectClass *) obj->klass;
  klass->get_is_alive_func = get_is_alive_func;
}

void game_object_set_is_collide_func (GameObject * self,
                               GameObjectGetIsCollideFunc get_is_collide_func) {
  Object * obj = (Object *) self;
  GameObjectClass * klass = (GameObjectClass *) obj->klass;
  klass->get_is_collide_func = get_is_collide_func;
}
#endif

/* ****************************************************************************/
void _game_object_private_set_visible (GameObject * self , bool visible) {
  self->visible = visible;
}

bool _game_object_private_get_visible (GameObject * self) {
  return self->visible;
}

/**  MOOOOO!  **/
