#include "image.hpp"

#include "renderer.hpp"

// vector_lookup
#include "common.hpp"

#include <cassert>

using std::vector;

Image::Image()
{
  gelements empty;
  // 10 empty layers for normal objects
  // and 10 for overlay
  for (int i = 0; i < 20; ++i)
    elements.push_back(empty);
}

Image::~Image()
{
  imlib_context_set_image(image_data);
  imlib_free_image();
}

void Image::clear()
{
  int layer = 0;

  for (layers::iterator liter = elements.begin(), lend = elements.end(); 
       liter != lend; ++liter, ++layer)
    if (layer < 10)
      for (gelements::iterator giter = liter->begin(), gend = liter->end(); 
	   giter != gend; ++giter)
	delete *giter;
  
  clear_no_delete();
}

void Image::clear_no_delete()
{
  int layer = 0;

  for (layers::iterator liter = elements.begin(), lend = elements.end(); 
       liter != lend; ++liter, ++layer)
    if (layer < 10)
      liter->clear();
}

void Image::clone(const layers& l)
{
  layers::iterator eiter = elements.begin();

  for (layers::const_iterator liter = l.begin(), lend = l.end(); 
       liter != lend; ++liter, ++eiter)
    for (gelements::const_iterator giter = liter->begin(), gend = liter->end(); 
	 giter != gend; ++giter)
      eiter->push_back((*giter)->clone());
}

void Image::add(GObj *g)
{
  assert(g->layer < 10);

  // add element
  gelements l = vector_lookup(elements, g->layer);
  l.push_back(g);

  // insert back into the vector, FIXME: might be slow
  elements[g->layer] = l;
}

void Image::overlay_add(GObj *g)
{
  assert(g->layer > 9);

  // add element
  gelements l = vector_lookup(elements, g->layer);
  l.push_back(g);

  // insert back into the vector, FIXME: might be slow
  elements[g->layer] = l;
}

void Overlay::add(GObj *g)
{
  // overlay
  g->layer += 10;

  elements.push_back(g);

  Render *render = Render::get_instance();
  render->current.overlay_add(g);
}

void Overlay::cleanup()
{
  partial_cleanup();

  Render *render = Render::get_instance();
  // draw = remove the overlay from screen
  render->draw("remove overlay:" + name, true);

  partial_cleanup_final();
}

void Overlay::partial_cleanup()
{
  Render *render = Render::get_instance();

  if (temp_elements.size() > 0)
    partial_cleanup_final();
  
  // remove from current
  for (std::vector<GObj*>::iterator giter = elements.begin(), 
	 gend = elements.end(); giter != gend; ++giter) {
    Image::layers::iterator liter = render->current.elements.begin() + (*giter)->layer;
    for (Image::gelements::iterator ogiter = liter->begin(), 
	   ogend = liter->end(); ogiter != ogend; ++ogiter)
      if ((*giter)->op_eq(*(*ogiter))) {
	liter->erase(ogiter);
	break;
      }
  }

  // add to previous
  for (std::vector<GObj*>::iterator giter = elements.begin(), 
	 gend = elements.end(); giter != gend; ++giter)
    render->previous.overlay_add(*giter);

  temp_elements = elements;
  elements.clear();
}

void Overlay::partial_cleanup_final()
{
  Render *render = Render::get_instance();

  // remove from previous since the overlay has been removed
  for (std::vector<GObj*>::iterator giter = temp_elements.begin(), 
	 gend = temp_elements.end(); giter != gend; ++giter) {
    Image::layers::iterator liter = render->previous.elements.begin() + (*giter)->layer;
    for (Image::gelements::iterator ogiter = liter->begin(), 
	   ogend = liter->end(); ogiter != ogend; ++ogiter)
      if ((*giter)->op_eq(*(*ogiter))) {
	liter->erase(ogiter);
	break;
      }
  }

  for (std::vector<GObj*>::iterator giter = temp_elements.begin(), 
	 gend = temp_elements.end(); giter != gend; ++giter)
    delete *giter;

  temp_elements.clear();
}
