#ifndef MATCH3FIELD_H_INCLUDED
#define MATCH3FIELD_H_INCLUDED

#include "include/Engine.h"



const cardinal CONST_MAX_FIELD_WIDTH = 11;
const cardinal CONST_MAX_FIELD_HEIGHT = 11;


const float CONST_MATCH3_CELL_WIDTH = 42.f;
const float CONST_MATCH3_CELL_HEIGHT = 42.f;
const float CONST_CHIP_LOWEST_SPEED = -0.5f;
const float CONST_CHIP_ACCELERATION = -0.0014f;

/*
const float CONST_MATCH3_CELL_WIDTH = 32.f;
const float CONST_MATCH3_CELL_HEIGHT = 32.f;
const float CONST_CHIP_LOWEST_SPEED = -0.3f;
const float CONST_CHIP_ACCELERATION = -0.001f;
*/
const cardinal CONST_MATCH_TIME = 150;

const float CONST_CHIP_POSITION_EPSILON = 1.f;
const float CONST_CHIP_VELOCITY_EPSILON = 0.3f;


const float CONST_CHIP_K = 0.4f;

const cardinal CONST_CHIP_TYPE_COUNT = 4;


struct TChipTemplateParams : public TSerializeInterface
{
	THalibutExternalAnimObject SelectedTemplateAnimObject;
	THalibutExternalAnimObject FinishingTemplateAnimObject;
	TRenderParams SelectedRenderParams;
	TRenderParams FinishingRenderParams;

	virtual void Serialize(boost::property_tree::ptree& propertyTree);

};


struct TMatch3FieldParams : public TSerializeInterface
{
	cardinal FieldWidth;
	cardinal FieldHeight;
	float CellWidth;
	float CellHeight;
	float ChipLowestSpeed;
	float ChipAcceleration;

	float ChipPositionEpsilon;
	float ChipVelocityEpsilon;
	float ChipK;
	cardinal ChipMatchTime;

	cardinal ChipTypeCount;

	std::vector<TChipTemplateParams> ChipTemplateParamsArr;

	TMatch3FieldParams()
		: FieldWidth(CONST_MAX_FIELD_WIDTH)
		, FieldHeight(CONST_MAX_FIELD_HEIGHT)
		, CellWidth(CONST_MATCH3_CELL_WIDTH)
		, CellHeight(CONST_MATCH3_CELL_HEIGHT)
		, ChipLowestSpeed(CONST_CHIP_LOWEST_SPEED)
		, ChipAcceleration(CONST_CHIP_ACCELERATION)
		, ChipPositionEpsilon(CONST_CHIP_POSITION_EPSILON)
		, ChipVelocityEpsilon(CONST_CHIP_VELOCITY_EPSILON)
		, ChipK(CONST_CHIP_K)
		, ChipMatchTime(CONST_MATCH_TIME)
		, ChipTypeCount(CONST_CHIP_TYPE_COUNT)
	{
		 
	}
	
	
	virtual void Serialize(boost::property_tree::ptree& propertyTree);

};


struct TChip
{
	int ChipType; // -1 means empty field
	std::string AnimName; //Generated automatically

	TRenderPairList::iterator RenderPair;

	cardinal VertexListShift;

	float Velocity;

	enum TChipState
	{
		CS_STANDBY,
		CS_SWAPPING,
		CS_FALLING,
		CS_LOCKED,
		CS_FINISHING,
		CS_X,
	} ChipState;

	TChip(int chipType, TRenderPairList::iterator renderPair, cardinal vertexListShift, TChipState chipState = CS_FALLING);

	~TChip();

	vec2 GetLeftBottomPos();
	void SetLeftBottomPos(vec2 newPos);
	void MoveLeftBottomPos(vec2 shift);

	static int StaticAnimationIndex;
	
};

struct TChipSwappingPair
{
	float T;
	ivec2 Chip1;
	ivec2 Chip2;

	vec2 Chip1RealPosFrom;
	vec2 Chip2RealPosFrom;

	bool IsReturning;


	TChipSwappingPair(ivec2 chip1, ivec2 chip2, vec2 chip1PosFrom, vec2 chip2PosFrom)
		: Chip1(chip1)
		, Chip2(chip2)
		, T(0)
		, Chip1RealPosFrom(chip1PosFrom)
		, Chip2RealPosFrom(chip2PosFrom)
		, IsReturning(false)
	{
	}

};

struct TChipDeletingData
{
	float T;
	ivec2 Chip;
	vec2 Pos;

	TChipDeletingData(ivec2 chip, vec2 pos)
		: T(0.f)
		, Chip(chip)
		, Pos(pos)
	{
	}
};

class TMatch3Logic
{
protected:

	cardinal ChipTypeCount;

	std::vector<std::vector<TChip> > ChipMatrix;
	std::vector<TChipSwappingPair> ChipSwappingPairVector;
	std::vector<TChipDeletingData> ChipDeletingVector;

	std::vector<TRenderPairList::iterator> RenderPairIteratorVector;

	ivec2 selectedChip;

	vec2 LeftBottomPosField;

	TMatch3FieldParams Match3FieldParams;

	void FillRandomChipMatrix(std::vector<TRenderPairList::iterator> renderPairIteratorVector, vec2 leftBottomPos);

	vec2 GetExpectedLeftBottomPos(cardinal x, cardinal y);

	void StartAnimateChip(cardinal x, cardinal y);
	void StopAnimateChip(cardinal x, cardinal y);

	bool ChipIsLocked(ivec2 chip);
	bool ChipIsFinishing(ivec2 chip);
	bool ChipIsStable(ivec2 chip);
	bool ChipCanBeSelected(ivec2 chip);
	bool ChipsCanBeSwapped(ivec2 p1, ivec2 p2);

	bool ChipCanBeMatchedUp(ivec2 chip);
	bool ChipCanBeMatchedDown(ivec2 chip);
	bool ChipCanBeMatchedLeft(ivec2 chip);
	bool ChipCanBeMatchedRight(ivec2 chip);

	void UnmatchChips(std::vector<ivec2> chipList);
	void UpdateChipPosition(cardinal dt);
	void RemoveBubbles();

	void ReplaceAnimation(ivec2 p);

	void MoveVertexListShiftBack(TRenderPairList::iterator renderPairItr, cardinal moveFrom);
	void MoveVertexCoordDown(TRenderPairList::iterator renderPairItr, cardinal moveFrom, float value);

	void AddChipToUp(cardinal colNum, int chipType, vec2 spawnPos, TChip::TChipState chipState = TChip::CS_FALLING);
	void InsertEmptyChip(cardinal colNum, cardinal rowNum, int chipType);

	void UpdateChipSwapping(cardinal dt);
	void TryMatchAllChips();

	void DestroyChip(ivec2 p);

	void ChangeChipType(ivec2 p);

public:

	TMatch3Logic();
	virtual ~TMatch3Logic();

	void SelectChip(ivec2 pos);
	void UnselectChip();
	ivec2 GetSelectedChip();

	std::vector<ivec2> GetAvailableMatchingChips();

	void SwapChips(ivec2 p1, ivec2 p2, bool isReturning = false);

	void ResetChipPos(ivec2 p);

	void UpdateLogic(cardinal dt);

	void HitFieldWithPattern(ivec2 pos, std::vector<std::vector<char> > pattern, std::vector<std::vector<char> > jumpingPattern);


};


class TMatch3Controller;

class TMatch3Field : public TMatch3Logic, public TInstancingWidgetAncestor
{
protected:
	 void FillBasicChipMatrixAndTriangleList();
	 
	 //TMatch3Controller& Match3Controller;

	 vec2 LastTappedPos;
	 vec2 LastMovePos;

	 ivec2 PosToChip(vec2 pos);
	 
public:
	TMatch3Field();
	TMatch3Field(const TMatch3Field& m);
	TMatch3Field& operator=(const TMatch3Field& m);
	
	TMatch3Field(TMatch3Controller& match3Controller);
	~TMatch3Field();

	virtual void Update(cardinal dt);
	virtual void OnTapDown(vec2 pos);
	virtual void OnTapUp(vec2 pos);
	virtual void OnMove(vec2 shift);
	virtual bool CheckClick(vec2 mousePos);

	void HighlightMatch3();
	
};










#endif
