package simogl.gamecore;

import simogl.camera.Camera;
import simogl.effect.particle.AbstractParticleEffect;
import simogl.effect.particle.custom.Rain;
import simogl.gameobjects.AbstractGameObject;
import simogl.gameobjects.building.AbstractBuilding;
import simogl.gui.ResourcePanel;
import simogl.level.AbstractLevel;

/**
 * This class is used to update all the game objects. It is a special
 * thread that calls all neccessary update()-methods. You will only need 
 * one obect of this class
 * @author Frank Bruns
 *
 */
public class Updater extends Thread
{
	private boolean isRunning = false;
	private long currentTime = 0L;
	private long elapsedTime = 0L;
	
	/**
	 * Creates a new Updater object
	 *
	 */
	public Updater()
	{
		this.isRunning = true;
		this.currentTime = System.currentTimeMillis();
	}
	
	/**
	 * Pauses the Updater. Is equal to pausing the game.
	 *
	 */
	public void pause()
	{
		this.isRunning = false;
	}
	
	/**
	 * Starts/Resumes the Updater. Is equal to starting/resuming the game.
	 */
	public void restart()
	{
		this.isRunning = true;
	}
	
	/**
	 * run()-method of the Updater thread. Place all actions here.
	 */
	@Override
	public void run()
	{
		while(this.isRunning)
		{
			// calculate the elapsed time since the last loop		
			this.elapsedTime = System.currentTimeMillis()-this.currentTime;
			this.currentTime += this.elapsedTime;
			
			this.updateThings(this.elapsedTime);			
			try
			{				
				Updater.sleep(40);
			}
			catch(InterruptedException e) 
			{
				System.out.println("Problem with \"sleep\" in Updater thread");
				e.printStackTrace();
			}
		}
	}
	
	/**
	 * Helper method to call all neccessary update() methods 
	 * @param elapsedTime time between two frames
	 */
	private synchronized void updateThings(long elapsedTime)
	{
		// update buildings
		for(AbstractGameObject building : AbstractLevel.buildings)
		{
			building.update(elapsedTime);
		}
		
		// update characters
		for(AbstractGameObject character : AbstractLevel.characters)
		{
			character.update(elapsedTime);			
		}
		
		// update different types of particle effects (except rain)
		for(AbstractParticleEffect effect : AbstractLevel.partEffects)
		{
			effect.update(elapsedTime);
		}		
		
		// update rain sources
		for(Rain rainSource : AbstractLevel.rainSources)
		{
			rainSource.update(elapsedTime);
		}
		
		// update Resources
		AbstractLevel.gold.update(elapsedTime);
		AbstractLevel.food.update(elapsedTime);
		ResourcePanel.setLabelInhabitants(Integer.toString(AbstractBuilding.getTotalNumberInhabitants()));
	}
	
}
