/*
	Copyright 2014 Michele "King_DuckZ" Santullo

	This file is part of CloonelJump.

	CloonelJump is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	CloonelJump is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with CloonelJump.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "tiledwallpaper.hpp"
#include "texture.hpp"
#include "sdlmain.hpp"
#include "sizeratio.hpp"
#include <cassert>

namespace cloonel {
	namespace {
		float2 CountTilesInScreen ( const ushort2& parScreenSize, const ushort2& parTileSize ) __attribute__((pure));

		///----------------------------------------------------------------------
		///----------------------------------------------------------------------
		float2 CountTilesInScreen (const ushort2& parScreenSize, const ushort2& parTileSize) {
			assert(ushort2(0) != parTileSize);
			return static_cast<float2>((parTileSize - 1 + parScreenSize) / parTileSize);
		}
	} //unnamed namespace

	///--------------------------------------------------------------------------
	///--------------------------------------------------------------------------
	TiledWallpaper::TiledWallpaper (const std::string&& parPath, SDLMain* parMain) :
		Drawable(128.0f, 128.0f),
		m_tileCount(parMain, ushort2(128)),
		m_tile(new Texture(parPath, parMain, false))
	{
	}

	///--------------------------------------------------------------------------
	///--------------------------------------------------------------------------
	TiledWallpaper::~TiledWallpaper() noexcept {
	}

	///--------------------------------------------------------------------------
	///--------------------------------------------------------------------------
	void TiledWallpaper::Reload() {
		m_tile->Reload();
	}

	///--------------------------------------------------------------------------
	///--------------------------------------------------------------------------
	void TiledWallpaper::Destroy() noexcept {
		m_tile->Destroy();
	}

	///--------------------------------------------------------------------------
	///--------------------------------------------------------------------------
	void TiledWallpaper::Draw() const {
		const ushort2 grid(static_cast<ushort2>(m_tileCount.tileCount()));
		const float2& sz = m_tileCount.tileSize();

		//TODO: add code to tell the renderer if the current tile will need clipping or not
		float2 dest;
		dest.y() = 0.0f;
		for (uint16_t y = 0; y < grid.y(); ++y) {
			dest.x() = 0.0f;
			for (uint16_t x = 0; x < grid.x(); ++x) {
				m_tile->Render(dest, sz, float2(1.0f), true);
				dest.x() += sz.x();
			}
			dest.y() += sz.y();
		}
	}

	///--------------------------------------------------------------------------
	///--------------------------------------------------------------------------
	TiledWallpaper::TileCountNotifiable::TileCountNotifiable (SDLMain* parMain, const ushort2& parTileSize) :
		BaseClass(parMain),
		m_tileCount(CountTilesInScreen(parMain->WidthHeight(), parTileSize)),
		m_tileSize(static_cast<float2>(parTileSize))
	{
		assert(parMain);
		assert(ushort2(0) != parTileSize);
	}

	///--------------------------------------------------------------------------
	///--------------------------------------------------------------------------
	void TiledWallpaper::TileCountNotifiable::NotifyResChanged (const SizeRatio& parSize) {
		BaseClass::NotifyResChanged(parSize);
		m_tileCount = CountTilesInScreen(static_cast<ushort2>(parSize.Resolution()), static_cast<ushort2>(m_tileSize));
#if !defined(NDEBUG)
		{
			const ushort2 tileSize(static_cast<ushort2>(m_tileSize));
			const ushort2 screenRes(static_cast<ushort2>(parSize.Resolution()));
			const ushort2 tileCount(static_cast<ushort2>(m_tileCount));
			assert(tileCount * tileSize < screenRes + tileSize);
		}
#endif
	}
} //namespace cloonel
