/*
   Copyright (C) 2013 Samuel Kogler

   This program 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 2 of the License, or
   (at your option) any later version.

   This program 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 this program; if not, write to the Free Software Foundation,
   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#ifndef OGRETERRAINMATERIALGENERATOREMBER_H
#define OGRETERRAINMATERIALGENERATOREMBER_H

#include <OgreTerrainMaterialGenerator.h>
#include <sigc++/signal.h>

namespace Ogre {
class TerrainGroup;
}
namespace Ember {
namespace OgreView {
struct IPageDataProvider;

namespace Terrain {


/**
 * @brief A simple material generator which doesn't do anythings special.
 * @see EmberTerrainProfile for more information.
 */
class OgreTerrainMaterialGeneratorEmber : public Ogre::TerrainMaterialGenerator {
public:
	OgreTerrainMaterialGeneratorEmber() = default;

protected:

	void _renderCompositeMap(size_t size, const Ogre::Rect& rect,
							 const Ogre::MaterialPtr& mat,
							 const Ogre::TexturePtr& destCompositeMap) override;

};


/**
 * @brief A material generator profile that always uses the material generated by Ember.
 * Most parameters and settings are ignored.
 */
class EmberTerrainProfile : public Ogre::TerrainMaterialGenerator::Profile {
public:
	const static std::string ERROR_MATERIAL;

	EmberTerrainProfile(IPageDataProvider& dataProvider,
						const Ogre::TerrainGroup& terrainGroup,
						Ogre::TerrainMaterialGenerator* parent,
						sigc::signal<void, const Ogre::TRect<Ogre::Real>&>& terrainShownSignal);

	~EmberTerrainProfile() override = default;

	/** Return whether this profile supports using a compressed
	        vertex format. This is only possible when using shaders.
	 */
	bool isVertexCompressionSupported() const override {
		// TODO SK: not supported for now
		return false;
	}

	/** Triggers the generator to request the options that it needs.
	 */
	void requestOptions(Ogre::Terrain* terrain) override;

	/** Generate a material for the given terrain using the active profile.
	 */
	Ogre::MaterialPtr generate(const Ogre::Terrain* terrain) override;

	/** Generate a material for the given composite map of the terrain using the active profile.
	 */
	Ogre::MaterialPtr generateForCompositeMap(const Ogre::Terrain* terrain) override;

	/** Whether to support a light map over the terrain in the shader,
	   if it's present (default true).
	 */
	void setLightmapEnabled(bool enabled) override {
		// We don't use this.
	}

	/** Get the maximum number of layers supported with the given terrain.
	   @note When you change the options on the terrain, this value can change.
	 */
	Ogre::uint8 getMaxLayers(const Ogre::Terrain* terrain) const override {
		// We don't use this.
		return 0;
	}


	/** Update parameters for the given terrain.
	 */
	void updateParams(const Ogre::MaterialPtr& mat, const Ogre::Terrain* terrain) override {
	}

	/** Update parameters for the given terrain composite map using the active profile.
	 */
	void updateParamsForCompositeMap(const Ogre::MaterialPtr& mat, const Ogre::Terrain* terrain) override {
		// We don't use this.
	}


protected:
	IPageDataProvider& mDataProvider;

	const Ogre::TerrainGroup& mTerrainGroup;

	/**
	 * @brief A template material to use whenever an error material is needed.
	 *
	 * Since the terrain system takes care of destroying any materials used in pages we can't use this directly; we need to use a clone.
	 */
	Ogre::MaterialPtr mErrorMaterialTemplate;

	/**
	 * @brief Gets a clone of the supplied material, or creates a clone if none is found.
	 * @param templateMaterial A template material.
	 * @param suffix A suffix used together with the name of the template material.
	 * @return A valid material pointer.
	 */
	static Ogre::MaterialPtr getOrCreateMaterialClone(const Ogre::MaterialPtr& templateMaterial, const std::string& suffix);

	sigc::signal<void, const Ogre::TRect<Ogre::Real>&>& mTerrainShownSignal;

};
} /* Terrain */
} /* OgreView */
} /* Ember */

#endif /* end of include guard: OGRETERRAINMATERIALGENERATOREMBER_H */
