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

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

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

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

#include <algorithm>
#include <limits>
#include <list>

#include <memory>
//#include <boost/smart_ptr.hpp>
#include <boost/function.hpp>
#include <boost/foreach.hpp>
#include <boost/array.hpp>

#pragma once

#define foreach         BOOST_FOREACH
#define reverse_foreach BOOST_REVERSE_FOREACH

#pragma warning (disable: 4127)

namespace Halley {
	// Boost
	using std::shared_ptr;
	using std::weak_ptr;
	using std::dynamic_pointer_cast;
	using std::static_pointer_cast;
	using boost::function;
	using boost::array;

	// Standard
	using std::min;
	using std::max;
	using std::swap;



	// Forward references
	class Frame;
	class Sprite;
	class InputKeyboard;
	class Thread;
	class Texture;


	// Smart pointers
	typedef shared_ptr<Frame> spFrame;
	typedef weak_ptr<Frame> wpFrame;
	typedef shared_ptr<Sprite> spSprite;
	typedef weak_ptr<Sprite> wpSprite;
	typedef shared_ptr<InputKeyboard> spInputKeyboard;
	typedef weak_ptr<InputKeyboard> wpInputKeyboard;
	typedef shared_ptr<Thread> spThread;
	typedef weak_ptr<Thread> wpThread;
	typedef shared_ptr<Texture> spTexture;
	typedef weak_ptr<Texture> wpTexture;

	//#include <boost/pool/pool_alloc.hpp>
	//typedef std::list<spSprite, boost::fast_pool_allocator<spSprite> > SpriteList;
	typedef std::list<spSprite> SpriteList;
	typedef SpriteList::iterator SpriteIter;

	// Mid function
	template <typename T>
	inline T mid(T minValue, T value, T maxValue)
	{
		return min(max(minValue, value), maxValue);
	}

	template <typename T>
	inline T maxAbs(T a, T b)
	{
		return abs(a) > abs(b) ? a : b;
	}

	template <typename T>
	inline T minAbs(T a, T b)
	{
		return abs(a) < abs(b) ? a : b;
	}

	template <typename T>
	inline bool rangeIntersection(T s1, T e1, T s2, T e2)
	{
		return (s1 < e2) && (s2 < e1);
	}


	// Endianness conversion
	//const bool IS_BIG_ENDIAN = *((short*)"AB") == 0x4243;
	const bool IS_BIG_ENDIAN = false;

	template <typename T>
	inline T FixEndian(T t)
	{
		if (IS_BIG_ENDIAN) {
			T temp = t;
			Uint8 *v = reinterpret_cast<Uint8*>(&temp);
			for (size_t i=0; i<sizeof(T)/2; i++) {
				swap(v[i], v[sizeof(T)-1-i]);
			}
			return temp;
		} else {
			return t;
		}
	}

	template<>
	inline Sint8 FixEndian<Sint8>(Sint8 t) {
		return t;
	}

	template<>
	inline Uint8 FixEndian<Uint8>(Uint8 t) {
		return t;
	}

	// True modulo definition
	template <typename T>
	inline T modulo (T a, T b)
	{
		T res = a % b;
		if (res < 0) res = b+res;
		return res;
	}

	// Float floor division (e.g. -0.5 / 2 = -1.0)
	template <typename T>
	inline T floorDivFloat (T a, T b)
	{
		return floor(a / b);
	}

	// Int floor division (e.g. -2 / 3 = -1)
	template <typename T>
	inline T floorDivInt (T a, T b)
	{
		T result = a / b;
		if (a % b < 0) result--;
		return result;
	}

	// Generic floor divs
	inline float floorDiv (float a, float b) { return floorDivFloat(a, b); }
	inline double floorDiv (double a, double b) { return floorDivFloat(a, b); }
	inline long floorDiv (long a, long b) { return floorDivInt(a, b); }
	inline int floorDiv (int a, int b) { return floorDivInt(a, b); }
	inline short floorDiv (short a, short b) { return floorDivInt(a, b); }
	inline char floorDiv (char a, char b) { return floorDivInt(a, b); }
}
