package playlist;

import _gestioneeventi.*;
import brano.*;
import contiene.*;
import player.*;
import java.util.*;

import eventi.Done;
import eventi.Play;
import eventi.PlaySong;
import eventi.Reset;
import eventi.StopSong;

public class PlayList implements Listener {
	private final String nome;
	private ArrayList<TipoLinkContiene> insieme_link;

	public PlayList(String n) {
		nome = n;
		insieme_link = new ArrayList<TipoLinkContiene>();
	}

	public String getNome() {
		return nome;
	}

	public void inserisciLinkContiene(TipoLinkContiene t) {
		if (t != null && t.getPlayList() == this)
			ManagerContiene.inserisci(t);
	}

	public void eliminaLinkContiene(TipoLinkContiene t) {
		if (t != null && t.getPlayList() == this)
			ManagerContiene.elimina(t);
	}

	public List<TipoLinkContiene> getLinkContiene() {
		return (ArrayList<TipoLinkContiene>) insieme_link.clone();
	}

	public void inserisciPerManagerContiene(ManagerContiene a) {
		if (a != null && !insieme_link.contains(a.getLink()))
			insieme_link.add(a.getLink());
	}

	public void eliminaPerManagerContiene(ManagerContiene a) {
		if (a != null)
			insieme_link.remove(a.getLink());
	}

	public int durataTotale() {
		int result = 0;
		Iterator<TipoLinkContiene> il = insieme_link.iterator();
		while (il.hasNext()) {
			Brano b = il.next().getBrano();
			result = result + b.getDurata();
		}
		return result;
	}

	// gestione stato

	public enum Stato {
		ATTESA, ESECUZIONE
	}

	private Stato statocorrente = Stato.ATTESA;

	private Player player;
	private int prossimobrano = 0;

	public Stato getStato() {
		return statocorrente;
	}

	public Evento fired(Evento e) {
		// filtra eventi non per this o non in broadcasting
		if (e.getDestinatario() != this && e.getDestinatario() != null)
			return null;

		Evento nuovoevento = null;
		switch (statocorrente) {
		case ATTESA:
			if (e.getClass() == Play.class)
				if (insieme_link.size() > 0) {
					player = ((Play) e).getPlayer();
					Brano b = insieme_link.get(prossimobrano).getBrano();
					prossimobrano++;
					nuovoevento = new PlaySong(this, player, b);
					statocorrente = Stato.ESECUZIONE;
				}
			break;
		case ESECUZIONE:
			if (e.getClass() == Done.class)
				if (prossimobrano < insieme_link.size()) {
					Brano b = insieme_link.get(prossimobrano).getBrano();
					prossimobrano++;
					nuovoevento = new PlaySong(this, player, b);
					statocorrente = Stato.ESECUZIONE;
				} else {
					player = null;
					prossimobrano = 0;
					statocorrente = Stato.ATTESA;
				}
			else if (e.getClass() == Reset.class) {
				nuovoevento = new StopSong(this, player);
				player = null;
				prossimobrano = 0;
				statocorrente = Stato.ATTESA;
			}
			break;
		default:
			throw new RuntimeException("Stato corrente non riconosciuto.");
		}
		return nuovoevento;
	}
}
