//
//  Node.h
//  PixelKit
//
//  Copyright (c) 2014 César Parent. All rights reserved.
//
#ifndef _NODE_H
#define _NODE_H

#include "includes.h"
#include "CollisionBody.h"
#include "Point.h"

namespace PixelKit
{
	class Layer;
	
	/*!
	 * @class
	 * @brief Node is the root object of PixelKit. It is drawn on the screen
	 * once it is made a child of a Layer or a scene.
	 * @namespace PixelKit
	 */
	class Node
	{
	public:
		/*!
		 * @brief controls wether the node is drawn on the screen
		 */
		bool visible;
		
		/*!
		 * @brief  SpriteNode's body used for collision simulation
		 */
		CollisionBody collisionBody;
		
		/*!
		 * @brief Remove the Node from its parent layer
		 */
		virtual void removeFromParent();
		
		/*!
		 * @brief contains the Node update code ran before rendering each frame
		 * @param timeInterval the time elapsed since last frame in milliseconds
		 */
		virtual void update(int timeInterval){};
		
		/*!
		 * @brief draw the Node to the screen
		 * @param renderer The SDL_Renderer used to draw the current game
		 */
		virtual void draw(SDL_Renderer *renderer){};
		
		/*!
		 * @brief Delegate method called when the node is added to the tree
		 */
		virtual void didBecomeChild() {};
		
		/*!
		 * @brief Delegate method called when the node is removed from the tree;
		 */
		virtual void didExitParent() {};
		
		/* getters and setters */
		
		/*!
		 * @brief register the Node as a children of a Layer
		 * @param parent Node's new parent
		 */
		virtual void setParent(Layer *parent);
		
		/*!
		 * @brief Node's parent, or null if the Node is an orphan
		 */
		virtual Layer *getParent();
		
		/*!
		 * @brief change the Node's coordinate along the X axis
		 * @param x Node's new X coordinate
		 */
		virtual void setX(float x);
		
		/*!
		 * @brief change the Node's coordinate along the Y axis.
		 * @param y the Node's new Y coordinate
		 */
		virtual void setY(float y);
		
		/*!
		 * @brief change the Node's X,Y coordinates.
		 * @param x Node's new X coordinate
		 * @param y Node's new Y coordinate
		 */
		virtual void setPosition(float x, float y);
		
		/*!
		 * @brief Change the Node's anchor point. The Anchor point represents
		 * where the coordinates point in the Node's area. 0,0 mean the Node is
		 * pinned by its upper left corner, 1.0,1.0 its lower right corner.
		 
		 * @param x horizontal location of the anchor point in the node
		 * @param y vertical location of the anchor point in the node
		 */
		virtual void setAnchorPoint(float x, float y);
		
		/*!
		 * @brief set the Node's size in pixels.
		 * @param w Node's new width
		 * @param h Node's new height
		 */
		virtual void setSize(int w, int h);
		
		/*!
		 * @brief set the Node's rotation in degrees.
		 * @param r the Node's new rotation angle.
		 */
		virtual void setRotation(float r);
		
		/*!
		 * @brief set the Node's horizontal scaling factor.
		 * @param scale The Node's new x scaling factor
		 */
		virtual void setXScale(float scale);
		
		/*!
		 * @brief set the Node's horizontal scaling factor.
		 * @param scale The Node's new y scaling factor
		 */
		virtual void setYScale(float scale);
		
		/*!
		 * @brief  Register Node for collision simulation, and create a
		 * a rectangle collider, located at (xOffset, yOffset) in the Node's
		 * frame, of size (w,h).
		 * @param xOffset CollisionBody's x position in the node's frame.
		 * @param yOffset CollisionBody's y position in the node's frame.
		 * @param w       CollisionBody's width.
		 * @param h       CollisionBody's height.
		 */
		virtual void addCollisionBody(int xOffset, int yOffset, int w, int h);
		
		/*!
		 * @brief Node's coordinates on screen.
		 */
		const Point<float> &position;
		
		/*!
		 * @brief Node's anchor point.
		 */
		const Point<float> &anchorPoint;
		
		/*!
		 * @brief Node's rotation angle.
		 */
		const float &rotation;
		
		/*!
		 * @brief Node's coordinates on screen.
		 */
		const SDL_Rect &frame;
		
		/*!
		 * @brief Controls wether Node is checked for collision.
		 */
		const bool &collidable;
		
		/*!
		 * @brief Node's horizontal scaling factor.
		 */
		const float &xScale;
		
		/*!
		 * @brief Node's vertical scaling factor.
		 */
		const float &yScale;
		
		/*!
		 * @brief Node's user-friendly name.
		 */
		std::string name;
		
		/*!
		 * @brief Node's constructor.
		 */
		Node();
		
		/*!
		 * @brief Node's destructor.
		 */
		virtual ~Node();
		
		/*!
		 * @brief Prints out a summary of the Node.
		 *
		 */
		friend std::ostream& operator<< (std::ostream &out, Node &node);
		
	protected:
		SDL_Rect _frame;
		Point<float> _position;
		Point<float> _anchorPoint;
		Point<float> _scale;
		Point<int> _unscaledSize;
		float _rotation;
		Layer* _parent;
		bool _collidable;
		int _flip;
		
	private:
		void updateCollisionBody();
	};
}

#endif