/// Copyright (c) 2010 Ruben Penalva. All rights reserved.
/// Redistribution and use in source and binary forms, with or without modification, 
/// are permitted provided that the following conditions are met:
///    1. Redistributions of source code must retain the above copyright notice, this 
///    list of conditions and the following disclaimer.
///    2. Redistributions in binary form must reproduce the above copyright notice,
///    this list of conditions and the following disclaimer in the documentation and/or
///    other materials provided with the distribution.
///    3. The name of the author may not be used to endorse or promote products derived
///    from this software without specific prior written permission.
///
/// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
/// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
/// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 
/// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 
/// TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
/// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
/// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 
/// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

/// @file Logic.h
/// This source file is part of CUDA Ray Casting test.
/// The file holds the Logic class interface.
/// @author Ruben Penalva (ruben.penalva@rpenalva.com)

#ifndef _LOGIC_H_
#define _LOGIC_H_

#include "Vector3.h"
#include "Matrix4x4.h"
#include "boost/smart_ptr/shared_array.hpp"

#include "MouseState.h"

namespace CUDARayCasting
{

/// @brief It handles all the logic of the test. Its called by Runner, 
/// which act as a controller between Logic and Render.
class Logic
{
public:
	/// Constructor
	Logic(void);

	/// Destructor
	~Logic(void);

	boost::shared_array<unsigned char> LoadVolumeData(void) const;

	boost::shared_array<float> LoadTransferFunction(void);

	void UpdateTransferFunction(float elpasedTime);

	void IncreaseStep(void);

	void DecreaseStep(void);

	void IncreaseStepNumber(void);

	void DecreaseStepNumber(void);

	void IncreaseAnimationTime(void);

	void DecreaseAnimationTime(void);
	
	void Pause(void);

	void Play(void);

	float GetStep(void) const;

	int GetStepNumber(void) const;

	float GetAnimationTime(void) const;

	bool IsStepIncreseable(void) const;

	bool IsStepDecreseable(void) const;

	bool IsStepNumberIncreseable(void) const;

	bool IsStepNumberDecreseable(void) const;

	bool IsAnimationTimeIncreseable(void) const;

	bool IsAnimationTimeDecreseable(void) const;

	bool IsPaused(void) const;

	void ProcessMouse(const GlutWrapper::MouseState& mouseState, float elapsedTime);

	const Matrix4x4& GetViewMatrix(void) const;
	
	const Matrix4x4& GetVolumeMatrix(void) const;

	int GetDensityWindowWidth(void) const;

	int GetDensityWindowBegin(void) const;

	int GetDensityWindowEnd(void) const;

	const Vector3& GetBboxMin(void) const;

	const Vector3& GetBboxMax(void) const;

private:
	static const int m_colorElementsCount;
	static const int m_tableColorsCount;
	static const int m_tableSize;
	static const Vector3 m_startColor;
	static const Vector3 m_endColor;
	static const float m_stepFixedAmount;
	static const float m_maxStep;
	static const float m_minStep;
	static const int m_stepNumberFixedAmount;
	static const int m_maxStepNumber;
	static const int m_minStepNumber;
	static const float m_animationTimeFixedAmount;
	static const float m_maxAnimationTime;
	static const float m_minAnimationTime;

	boost::shared_array<float> m_transferFunctionPtr;

	float m_totalElapsedTime;
	float m_dir;
	float m_step;
	int m_stepNumber;
	float m_animationTime;
	bool m_paused;

	Vector3 m_cameraPos;
	Vector3 m_cameraTarget;
	Vector3 m_cameraUp;
	Vector3 m_transCameraPos;
	Matrix4x4 m_viewMatrix;

	Matrix4x4 m_volumeMatrix;

	int m_densityWinWidth;
	int m_densityWinBegin;
	int m_densityWinEnd;

	Vector3 m_bboxMin;
	Vector3 m_bboxMax;

	/// @note hide copy constructor from interface user
	Logic(const Logic&);

	/// @note hide assignment operator from interface user
	Logic& operator=(const Logic&);
};

}

#endif