/*
 * This source file is part of KEOS (Free 3D Engine)
 * For the latest info, see http://www.keosengine.org/
 * E-mails : thierry.vouriot@keosengine.org, yeri@keosengine.org
 * 
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place - Suite 330, Boston, MA 02111-1307, USA, or go to
 * http://www.gnu.org/copyleft/lesser.txt.
 *
 */
#include "KeosConsoleLookDefault.h"
#include "KeosGraphicString.h"
#include "KeosConsoleLook.h"
#include "KeosConsole.h"
#include "KeosModel.h"
#include "KeosMatrix4.h"
#include "KeosRenderSystem.h"
#include "KeosFontManager.h"

namespace Keos {

	namespace Console {

		//=======================================================================
		// CLookDefault implementation
		//=======================================================================

		//-----------------------------------------------------------------------
		CLookDefault::CLookDefault(const String& strFont, TVector2F Size, const String& strTexture,
							const CColor& TextColor, const CColor& TextOkColor, const CColor& TextErrorColor) :
		m_State (STOPPED_INVISIBLE),
		m_strFont (strFont),
		m_nSize (Size),
		m_TextColor (CColor::White),
		m_TextOkColor (CColor(150, 200, 150)),
		m_TextErrorColor (CColor(200, 150, 150))
		{
			m_nFontHeight = CFontManager::Instance().GetFontHeight(strFont);

			// Background creation
			CModel::TVertex Vertices[] =
			{
				{TVector3F(		0,		0, 0), TVector3F(), Renderer->ConvertColor(CColor(255, 255, 255, 200)), TVector2F(0, 0)},
				{TVector3F(Size.x,		0, 0), TVector3F(), Renderer->ConvertColor(CColor(255, 255, 255, 200)), TVector2F(1, 0)},
				{TVector3F(		0, Size.y, 0), TVector3F(), Renderer->ConvertColor(CColor(255, 255, 255, 200)), TVector2F(0, 1)},
				{TVector3F(Size.x, Size.y, 0), TVector3F(), Renderer->ConvertColor(CColor(255, 255, 255, 200)), TVector2F(1, 1)}
			};
			CModel::TIndex Indices[] = {0, 1, 2, 2, 1, 3};
			m_Background = new CModel(Vertices, 4, Indices, 6, strTexture); 

			// Initial position: invisible
			m_Transfo.SetScaling(0, 0, 0);

			// Create the first line
			AddLine("> ", m_TextColor);

			// Register special command
			CConsole::Instance().RegisterCommand("clear", Bind(&std::list<CGraphicString>::clear, m_Lines));
			char str[128];
			sprintf(str,"Keos %s", CRoot::Instance().GetVersion().c_str());
			CConsole::Instance().RegisterCommand("ver", Bind(Print(String(str))));
		}

		//-----------------------------------------------------------------------
		void CLookDefault::Update()
		{
			static uint sTimeAtLastFrame = CRoot::Instance().GetTimer()->GetMilliseconds();
			uint nCurrentTime = CRoot::Instance().GetTimer()->GetMilliseconds();
			uint nFrameInterval = nCurrentTime - sTimeAtLastFrame;
			sTimeAtLastFrame = nCurrentTime;

			static float Scale = 0.0f;

			if (m_State == SHOWING)
			{
				m_Transfo.SetScaling(1, Scale, 1);
				Scale += nFrameInterval / 400.0f;

				if (Scale > 1.0f)
				{
					m_Transfo.SetScaling(1, 1, 1);
					m_State = STOPPED_VISIBLE;
					Scale   = 1.0f;
				}
			}
			else if (m_State == HIDDING)
			{
				m_Transfo.SetScaling(1, Scale, 1);
				Scale -= nFrameInterval / 400.0f;

				if (Scale < 0.01f)
				{
					m_Transfo.SetScaling(0, 0, 0);
					m_State = STOPPED_INVISIBLE;
					Scale   = 0.0f;
				}
			}
		}

		//-----------------------------------------------------------------------
		void CLookDefault::Draw() const
		{
			if (m_State != STOPPED_INVISIBLE)
			{
				Renderer->PushMatrix(MAT_MODELVIEW);
				Renderer->LoadMatrix(MAT_MODELVIEW, m_Transfo);

				Renderer->Enable(RENDER_ZWRITE, false);
				Renderer->Enable(RENDER_ALPHABLEND, true);
				Renderer->SetupAlphaBlending(BLEND_SRCALPHA, BLEND_INVSRCALPHA);

				m_Background->Render();

				Renderer->Enable(RENDER_ALPHABLEND, false);

				for (std::list<CGraphicString>::const_iterator i = m_Lines.begin(); i != m_Lines.end(); ++i)
					i->Draw();

				Renderer->Enable(RENDER_ZWRITE, true);

				Renderer->PopMatrix(MAT_MODELVIEW);
			}
		}

		//-----------------------------------------------------------------------
		void CLookDefault::Show(bool bVisible)
		{
			m_State = bVisible ? SHOWING : HIDDING;
		}

		//-----------------------------------------------------------------------
		void CLookDefault::CommandCalled(const String& strResult)
		{
			if (!strResult.empty())
				AddLine(strResult, m_TextOkColor);
			AddLine("> ", m_TextColor);
		}

		//-----------------------------------------------------------------------
		void CLookDefault::TextChanged(const String& strNewText)
		{
			m_Lines.front().Text = "> " + strNewText;
		}

		//-----------------------------------------------------------------------
		void CLookDefault::Error(const String& strMessage)
		{
			std::string Line;
			std::istringstream iss(strMessage);
			while (std::getline(iss, Line))
				AddLine(Line, m_TextErrorColor);

			AddLine("> ", m_TextColor);
		}

		//-----------------------------------------------------------------------
		void CLookDefault::AddLine(const String& strLine, const CColor& Color)
		{
			// Delete the last line if necessary
			if (m_Lines.size() == (int)(((float)m_nSize.y) / ((float)m_nFontHeight)))
				m_Lines.pop_back();

			// Move the others
			for (std::list<CGraphicString>::iterator i = m_Lines.begin(); i != m_Lines.end(); ++i)
			{
				i->Position.y -= (int)m_nFontHeight;
				i->Color.Set(i->Color.GetRed(), i->Color.GetGreen(), i->Color.GetBlue(), i->Color.GetAlpha() - 20);
			}

			// Create the new line
			m_Lines.push_front(CGraphicString(TVector2I((int)m_nFontHeight/2, m_nSize.y - (int)((float)m_nFontHeight*1.3)), strLine, Color, m_strFont));
		}

	} // namespace Console

} // namespace Keos
