/*********************************************************\
		 __      __           __  __
		/ /     / / _____    / / / / ______   __     __
	   / /     / / /___  \  / / / / / ___  | / /    / /
	  / /_____/ / _____| / / / / / / /__/ / / /    / /
	 / ______  / / ___  / / / / / / _____/ / /    / /
	/ /     / / / /__/ / / / / / / |____  / |____/ /
   /_/     /_/ |______/ /_/ /_/  \_____/  \_____  /
										 ______/ /
			High Level Game Framework   /_______/

  ------------------------------------------------------

  Copyright (c) 2007 - Rodrigo Braz Monteiro.
  This file is subject to the terms of license.txt.

\*********************************************************/

#pragma once

#include <list>
#include "utils.h"
#include "halleystring.h"
#include "vector2d.h"

namespace Halley {


	// FrameParent interface, used by both frames themselves and by the game core
	class IFrameParent {
	public:
		virtual ~IFrameParent() {}

		virtual void Exit()=0;
		virtual void ChildFrameChange(shared_ptr<Frame> from, shared_ptr<Frame> to)=0;
	};
	typedef weak_ptr<IFrameParent> wpFrameParent;
	typedef shared_ptr<IFrameParent> spFrameParent;


	// Frame class
	class Frame : public IFrameParent {
		friend class Game;

	private:
		String name;
		bool hasBeenInit;
		bool alive;

		wpFrameParent parent;
		wpFrame weakThis;
		spInputKeyboard kb;

		std::list<spFrame> children;

		void Destroy(spFrame newFrame);

		void ChildFrameChange(spFrame from,spFrame to);

		void SetParent(wpFrameParent parent, wpFrame weakThis);

	protected:
		virtual void Init() {}
		virtual void DeInit() {}
		virtual bool DoUpdate(float time)=0;
		virtual void DoRender()=0;

		void AddChild(spFrame child);
		void AddChild(String child);
		void Switch(spFrame to);
		void Switch(String to);

		Vector2f fieldSize;

	public:
		explicit Frame(String name);
		virtual ~Frame();

		void TryInit();
		void TryDeInit();

		void Die();
		void Exit();

		bool Update(float time);
		void Render();

		Vector2f getFieldSize() const;
		Vector2f getMaxDist() const;
		Vector2f makeVectorInside(Vector2f v) const;
	};

}
