//Copyright (C) Ben Parbury - All Rights Reserved. Unauthorized copying of this file, via any medium is strictly prohibited. Written by Ben Parbury <ben@gridlockinteractive.com> 2014
var gStatsSystem = new StatsSystem();

EStatsType =
{
	Time : "time",
	GameTime : "gameTime",
	ArcadeTime : "arcadeTime",
	Blocks : "blocks",
	Pushes : "pushes",
	Score : "score",
	UndeletedBlocks : "undeletedBlocks",
	DeletedBlocks : "deletedBlocks",
	Chain : "chain",
	Stars : "stars",
	Betters : "betters",
}

function StatsSystem()
{
	this.stats = new Array();
	this.lifetimeStats = new Array();
	this.startTimeMs = 0;
	this.gameTimeMs = 0;
	this.lastGameTimeUpdateMs = 0;
	this.arcadeTimeMs = 0;
	this.lastArcadeTimeUpdateMs = 0;
	this.arcadeScoreAdded = 0;
	
	this.Init = function()
	{
		for(var stat in EStatsType)
		{
			var index = EStatsType[stat];
			var value = gStorage.getItem("Stats", index);
			this.lifetimeStats[index] = value && !isNaN(value) ? Number(value) : 0;
			this.stats[index] = 0;
		}
		
		this.ResetTimers();
	}
	
	this.Clear = function()
	{
		this.SetStat(EStatsType.Time, this.GetStat(EStatsType.Time));
		for(var stat in EStatsType)
		{
			var index = EStatsType[stat];
			this.lifetimeStats[index] += this.stats[index];
			gStorage.setItem("Stats", index, this.lifetimeStats[index]);
			this.stats[index] = 0;
		}

		this.ResetTimers();
	}
	
	this.ResetTimers = function()
	{
		var currentTime = this.GetCurrentTimeMs();
		this.startTimeMs = currentTime;
		this.lastGameTimeUpdateMs = currentTime;
		this.lastArcadeTimeUpdateMs = currentTime;
		this.gameTimeMs = 0;
		this.arcadeTimeMs = 0;
		this.arcadeScoreAdded = 0;
	}
	
	this.IsValidStat = function(statType)
	{
		for(var stat in EStatsType)
		{
			if(EStatsType[stat] == statType)
			{
				return true;
			}
		}

		return false;
	}
	
	this.UpdateStat = function(statsType, increment)
	{
		gConsole.Assert(this.IsValidStat(statsType));
		gUndoSystem.AddRecord(new UndoStatsChange(statsType, this.stats[statsType]));
		this.stats[statsType] += increment;
		if(gLevelSystem.IsArcade() && statsType == EStatsType.Score)
		{
			var timeAdded = 0;
			var scoreD10 = Math.floor(this.arcadeScoreAdded/10);
			var extraTime = (increment * 1000 * Math.pow(0.95, scoreD10));
			this.arcadeTimeMs -= extraTime;
			this.arcadeScoreAdded += increment;
			
			gConsole.Log(3, "[ARCADE] " + increment + " equals " + extraTime.toFixed(3));
		}
	}
	
	this.SetStat = function(statsType, value)
	{
		gConsole.Assert(this.IsValidStat(statsType));
		this.stats[statsType] = value;
	}

	this.SetStatMax = function(statsType, value)
	{
		gConsole.Assert(this.IsValidStat(statsType));
		gUndoSystem.AddRecord(new UndoStatsChange(statsType, this.stats[statsType]));
		this.stats[statsType] = Math.max(value, this.stats[statsType]);
	}

	this.GetStat = function(statsType)
	{
		gConsole.Assert(this.IsValidStat(statsType));
		
		switch(statsType)
		{
			case EStatsType.Blocks:
				{
					return gBlockSystem.blocks.length;
				}
				break;
			case EStatsType.UndeletedBlocks:
				{
					return gBlockSystem.GetNonDeletingBlockCount();
				}
				break;
			case EStatsType.Time:
				{
					return Math.round((this.GetCurrentTimeMs() - this.startTimeMs)/1000);
				}
				break;
			case EStatsType.GameTime:
				{
					return Math.round(this.gameTimeMs/1000);
				}
				break;
			case EStatsType.ArcadeTime:
				{
					return Math.round(this.arcadeTimeMs/1000);
				}
				break;
			case EStatsType.Stars:
				{
					return this.GetStarsAllLevels();
				}
				break;
			case EStatsType.Betters:
				{
					return this.GetBettersAllLevels();
				}
				break;
		}
		
		return this.stats[statsType];
	}
	
	this.GetStarsAllLevels = function()
	{
		var stars = 0;
		for(levelSet in gLevelsBySet)
		{
			if(gLevelsBySet.hasOwnProperty(levelSet))
			{
				for(var i = 0; i < gLevelsBySet[levelSet].length; i++)
				{
					var levelName = gLevelsBySet[levelSet][i];
					var storedStars = gStorage.getItem(levelSet, levelName, "stars");
					if(storedStars)
					{
						stars += parseInt(storedStars);
					}
				}
			}
		}
		
		return stars;
	}
	
	this.GetBettersAllLevels = function()
	{
		var betters = 0;
		for(levelSet in gLevelsBySet)
		{
			if(gLevelsBySet.hasOwnProperty(levelSet))
			{
				for(var i = 0; i < gLevelsBySet[levelSet].length; i++)
				{
					var levelName = gLevelsBySet[levelSet][i];
					var better = gStorage.getItem(levelSet, levelName, "better");
					if(better)
					{
						betters++;
					}
				}
			}
		}
		
		return betters;
	}

	this.GetStarsForSet = function(levelSet)
	{
		var stars = 0;
		if(gLevelsBySet[levelSet])
		{
			for(var i = 0; i < gLevelsBySet[levelSet].length; i++)
			{
				var levelName = gLevelsBySet[levelSet][i];
				if(gLevelsBySet[levelName])
				{
					stars += this.GetStarsForSet(levelName);
				}
				else
				{
					var storedStars = gStorage.getItem(levelSet, levelName, "stars");
					if(storedStars)
					{
						stars += parseInt(storedStars);
					}
				}
			}
		}
		
		return stars;
	}
	
	this.GetMinStarsForSet = function(levelSet)
	{
		var stars = gRulesSystem.kStarCount;
		if(gLevelsBySet[levelSet])
		{
			for(var i = 0; i < gLevelsBySet[levelSet].length; i++)
			{
				var levelName = gLevelsBySet[levelSet][i];
				if(gLevelsBySet[levelName])
				{
					var currentForSet = this.GetMinStarsForSet(levelName);
					stars = Math.min(stars, currentForSet);
				}
				else
				{
					var storedStars = gStorage.getItem(levelSet, levelName, "stars");
					if(storedStars)
					{
						var current = parseInt(storedStars);
						stars = Math.min(stars, current);
					}
					else
					{
						return 0;
					}
				}
			}
		}
		
		return stars;
	}
	
	this.GetCountForSet = function(levelSet)
	{
		var set = levelSet.toLowerCase();
		if(gLevelsBySet[set])
		{
			var count = 0;
			for(var i = 0; i < gLevelsBySet[levelSet].length; i++)
			{
				var levelName = gLevelsBySet[levelSet][i];
				if(gLevelsBySet[levelName])
				{
					count += this.GetCountForSet(levelName);
				}
				else
				{
					count++;
				}
			}
			return count;
		}

		return 0;
	}
	
	this.GetLifetimeStat = function(statsType)
	{
		gConsole.Assert(this.IsValidStat(statsType));
		return this.lifetimeStats[statsType];
	}
	
	this.Debug = function()
	{
		for(var stat in EStatsType)
		{
			gDraw.Watch(EStatsType[stat] + " " + Math.round(this.GetStat(EStatsType[stat])));
		}
	}
	
	this.GetCurrentTimeMs = function()
	{
		return (new Date()).getTime();
	}
	
	this.Update = function()
	{
		var currentTime = this.GetCurrentTimeMs();
		if(!gPause.IsPaused())
		{
			this.gameTimeMs += currentTime - this.lastGameTimeUpdateMs;
			this.arcadeTimeMs += currentTime - this.lastArcadeTimeUpdateMs;
		}
		this.lastGameTimeUpdateMs = currentTime;
		this.lastArcadeTimeUpdateMs = currentTime;
	}
}