package kr.gui;

import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collection;

import javax.swing.Timer;
import javax.swing.event.MouseInputAdapter;

import kr.util.Listener;
import kr.util.ListenerManager;

/**
 * Allows panel to be updated based on the current time. Also, when playing, will update periodically
 */
public abstract class TimeSyncedController
{	
	private Component panel;
	
	private static MasterTimer masterTimer = new MasterTimer();

	public TimeSyncedController()
	{
		masterTimer.addController(this);
	}
		
	/**
	 * May be overridden by subclass
	 */
	protected void performTimedAction()
	{
		panel.repaint();
	}

	/**
	 * Should not be used unless performTimedAction is overridden. Otherwise use two argument init.
	 */
	protected void init(GuiModel guiModel) {
		masterTimer.init(guiModel);
	}

	protected void init(GuiModel guiModel, Component panel) {
		this.panel = panel;
		init(guiModel);
	}
	
	private static class MasterTimer implements Listener, ActionListener
	{
		private static final int UPDATE_TIME = 50;
		
		private GuiModel guiModel;
		private Timer timer = new Timer(UPDATE_TIME, this);
		private Collection<TimeSyncedController> controllers = new ArrayList<TimeSyncedController>();
			
		protected void init(GuiModel guiModel) {
			this.guiModel = guiModel;
			ListenerManager.inst().registerListener(guiModel, this);
		}
		
		public void addController(TimeSyncedController controller)
		{
			this.controllers.add(controller);
		}

		public void actionPerformed(ActionEvent e)
		{
			if(e.getSource() == timer)
				performTimedAction();
		}
		
		private void performTimedAction()
		{
			guiModel.updateFixedTime();
			for(TimeSyncedController c : controllers)
			{
				c.performTimedAction();
			}
		}
		
		public void notify(Object source, Object type, Object... values) {
			if(source == guiModel)
			{
				if((GuiModel.MessageType)type ==  GuiModel.MessageType.NOW_UPDATED)
				{
					long oldMicros = (Long)values[0];
					performTimedAction();
				}
				else if((GuiModel.MessageType)type ==  GuiModel.MessageType.IS_PLAYING_UPDATED)
				{
					if(guiModel.isPlaying())
					{
						timer.start();
					}
					else
					{
						timer.stop();
					}
					
				}
			}
		}
		
	}
}
