//#pragma once
#ifndef AnimationrigLogger_H
#define AnimationrigLogger_H

#include <CommonMemoryStream.h>
#include <AnimationrigMisc.h>
#include <Animationrig.h>
#include <AnimationrigState.h>

#include <vector>

using namespace std;

namespace Animrig {
	class Logger {
	public:
		static std::function<void(const wstring&)> onLog;
		static void log(const wstring &s)
		{
			if (onLog != nullptr) onLog(s);
		}
		static wstring floatToStr(float f)
		{
			// ignore -0.0000
			if ((f <= +0.0)&&(f > -0.0000001)) f = 0.0f;

			return std::_Floating_to_wstring(L"%.2f", f);
		}
		static wstring intToStr(int v)
		{
			return std::to_wstring(v);
		}
		static wstring boolToStr(bool b)
		{
			if (b)
				return L"true";
			else
				return L"false";
		}
		static wstring floatArrayToStr(float *array, int count)
		{
			wstring s = L"";
			for (auto i = 0; i < count; i++)
			{
				if (i > 0) s += L" , ";
				s += floatToStr(array[i]);
			}
			return s;
		}
		static wstring matrixToStr(Matrix4 &m)
		{
			wstring s = L"";
			s += floatToStr(m._11) + L"," + floatToStr(m._12) + L"," + floatToStr(m._13) + L"," + floatToStr(m._14);
			s += L" , " + floatToStr(m._21) + L"," + floatToStr(m._22) + L"," + floatToStr(m._23) + L"," + floatToStr(m._24);
			s += L" , " + floatToStr(m._31) + L"," + floatToStr(m._32) + L"," + floatToStr(m._33) + L"," + floatToStr(m._34);
			s += L" , " + floatToStr(m._41) + L"," + floatToStr(m._42) + L"," + floatToStr(m._43) + L"," + floatToStr(m._44);
			return s;
		}
		static wstring vectorToStr(Vector3 &v)
		{
			return floatToStr(v.x) + L" , " + floatToStr(v.y) + L" , " + floatToStr(v.z);
		}
	};
	class  StateLogRenderer : public StateRenderer {
	public:
		wstring name = L"";

		StateLogRenderer(ObjectType dummyobjecttype)
		{
			setObjectType(dummyobjecttype);
		}
		~StateLogRenderer() override	// virtual destructor override
		{
			//
		}

		// common
		void update(double deltatime) override
		{
			Logger::log(name + L".renderer.update : " + Logger::floatToStr((float)deltatime));
			Logger::log(name + L".renderer.state");
			Logger::log(L"  priority.z : " + Logger::floatToStr(drawPriorityZ));
			Logger::log(L"  priority.design : " + Logger::floatToStr(drawPriorityDesign));
			Logger::log(L"  enable : " + Logger::boolToStr(rendererEnable));
			Logger::log(L"  visible : " + Logger::boolToStr(rendererVisible));
			Logger::log(L"  color : " + Logger::floatArrayToStr(transColor,4));
			Logger::log(L"  matrix : " + Logger::matrixToStr(transMatrix));
		}
		// spine
		void setAnimation(int trackindex, int usetrack, const wstring &basename, bool loop, bool addanim, MixBlend trackmix, float duration, bool seekmode) override
		{
			Logger::log(name + L".renderer.SetAnimation");
			Logger::log(L"  track : " + Logger::intToStr(trackindex));
			Logger::log(L"  name : " + basename);
			Logger::log(L"  loop : " + Logger::boolToStr(loop));
			Logger::log(L"  addanimation : " + Logger::boolToStr(addanim));
			if (trackmix == MixBlend::Replace)
				Logger::log(L"  trackmix : replace");
			else
				Logger::log(L"  trackmix : add");
			Logger::log(L"  duration : " + Logger::floatToStr(duration));
			Logger::log(L"  seekmode : " + Logger::boolToStr(seekmode));
		}
		void setTrackBlendAlpha(int trackindex, int usetrack, float alpha1, float alpha2, float alpha3, float alpha4, bool exists) override
		{
			auto s = Logger::floatToStr(alpha1) + L" , " +
				Logger::floatToStr(alpha2) + L" , " +
				Logger::floatToStr(alpha3) + L" , " +
				Logger::floatToStr(alpha4);
			Logger::log(name + L".renderer.SetTrackBlendAlpha");
			Logger::log(L"  layer exists : " + Logger::boolToStr(exists));
			Logger::log(L"  track : " + Logger::intToStr(trackindex));
			Logger::log(L"  alpha : " + s);
		}
		void setTrackSeekTime(int trackindex, int usetrack, float time1, float time2, float time3, float time4, bool exists) override
		{
			auto s = Logger::floatToStr(time1) + L" , " +
				Logger::floatToStr(time2) + L" , " +
				Logger::floatToStr(time3) + L" , " +
				Logger::floatToStr(time4);
			Logger::log(name + L".renderer.SetTrackSeekTime");
			Logger::log(L"  layer exists : " + Logger::boolToStr(exists));
			Logger::log(L"  track : " + Logger::intToStr(trackindex));
			Logger::log(L"  time : " + s);
		}
		void setMixDuration(float duration) override
		{
			Logger::log(name + L".renderer.SetMixDuration : " + Logger::floatToStr(duration));
		}
	};
}

#endif

