using System;
using System.Collections.Generic;

namespace Cryville.Crtr {
	public abstract class StateBase<T> {
		public int EventId;
		public float Time;
		public Chart chart;
		public List<T> events;

		bool breakflag = false;
		
		public StateBase(Chart c, List<T> evs) {
			chart = c;
			events = evs;
			EventId = 0;
			Time = 0;
		}

		public virtual StateBase<T> Clone() {
			return (StateBase<T>)base.MemberwiseClone();
		}

		public virtual void CopyTo(StateBase<T> dest) {
			dest.EventId = EventId;
			dest.Time = Time;
			dest.breakflag = breakflag;
		}

		public virtual void Break() {
			breakflag = true;
		}

		public void Forward(Action<T> callback = null) {
			ForwardToTime(float.PositiveInfinity, callback);
		}

		public void ForwardByTime(float time, Action<T> callback = null) {
			ForwardToTime(Time + time, callback);
		}

		public void ForwardOnceByTime(float time, Action<T> callback = null) {
			ForwardOnceToTime(Time + time, callback);
		}

		public void ForwardToTime(float toTime, Action<T> callback = null) {
			breakflag = false;
			ForwardOnceToTime(Time, callback);
			while (Time < toTime) {
				ForwardOnceToTime(toTime, callback);
				if (breakflag) break;
			}
		}

		public void ForwardStepByTime(float time, float step, Action<T> callback = null) {
			ForwardStepToTime(Time + time, step, callback);
		}

		public void ForwardStepToTime(float toTime, float step, Action<T> callback = null) {
			breakflag = false;
			ForwardOnceToTime(Time, callback);
			while (Time < toTime) {
				float next = Time + step;
				ForwardOnceToTime(next < toTime ? next : toTime, callback);
				if (breakflag) break;
			}
		}
		
		public abstract void ForwardOnceToTime(float toTime, Action<T> callback = null);
	}
}
