#include <iostream>
#include "Component.h"

using namespace std;

Component::Component()
{
	parent = NULL;
	selected = false;
	t = vec3(0,0,0);
  tp = vec3(0,0,0);
	r = vec3(0,0,0);
	s = vec3(1.0,1.0,1.0);
  children.resize(0);
  sid = 0;
}

Component::Component(const Component& c)
{
	parent = c.parent;
	children = c.children;
	selected = c.selected;
	t = vec3(c.t.x, c.t.y, c.t.z);
  tp = vec3(c.tp.x, c.tp.y, c.tp.z);
	r = vec3(c.r.x, c.r.y, c.r.z);
	s = vec3(c.s.x, c.s.y, c.s.z);
  sid = c.sid;
}

void Component::draw(shared_ptr<MatrixStack> MV, shared_ptr<MatrixStack> P, shared_ptr<Shape> S, shared_ptr<Program> Prog)
{
  MV->pushMatrix();
  MV->translate(tp.x, tp.y, tp.z);
	MV->rotate(r.x, 1, 0, 0);
	MV->rotate(r.y, 0, 1, 0);
	MV->rotate(r.z, 0, 0, 1);
  MV->translate(t.x, t.y, t.z);
	for(unsigned int i = 0; i < children.size(); i++)
	{
		children[i].draw(MV, P, S, Prog);
	}
  if(selected)
  {
	  MV->scale(1.1,1.1,1.1);
  }
  MV->scale(s.x,s.y,s.z);
	glUniformMatrix4fv(Prog->getUniform("P"), 1, GL_FALSE, &P->topMatrix()[0][0]);
	glUniformMatrix4fv(Prog->getUniform("MV"), 1, GL_FALSE, &MV->topMatrix()[0][0]);
	S->draw(Prog);
  MV->popMatrix();
}

Component& Component::getLastChild()
{
  if(this->children.empty())
  {
    return *this;
  }
  return this->children[this->children.size() - 1].getLastChild();
}

Component& Component::getPrevious(Component *addr)
{
  if(children.empty())
  {
    if(parent != NULL)
    {
      return parent->getPrevious(this);
    }
  }

  for(unsigned int i = 0; i < this->children.size(); i++)
  {
    //return *this;
    if(&children[i] == addr)
    {
      if(i > 0)
      {
        return children[i-1].getLastChild();
      }
      else
      {
        return *this;
      }
    }
  }

  if (parent == NULL) {
    return this->getLastChild();
  }

  return parent->getPrevious(this);
}

Component& Component::getNext(Component *addr)
{
  if(addr == NULL)
  {
    if(!children.empty())
    {
      return children[0];
    }
  }

  for(unsigned int i = 0; i < this->children.size(); i++)
  {
    //return *this;
    if(&children[i] == addr)
    {
      if(i+1 < children.size())
      {
        return children[i+1];
      }
    }
  }

  if (parent == NULL) {
    return *this;
  }

  return parent->getNext(this);
}
