package bmserv.model.handlers;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.List;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

import bmserv.Writer;
import bmserv.model.Bookmark;
import bmserv.model.Tag;
import bmserv.model.Tagging;
import bmserv.model.User;
/**
 * Gestion des instances de {@link Tagging}.<br/>
 * Cette classe sert a faire le lien entre des differents elements du modele.
 * Un {@link Tagging} correspond a une action d'un utilisateur qui associe a un moment donne un {@link Tag} et un {@link Bookmark}.<br/>
 * @author ndelafor
 *
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "taggings")
public class TaggingHandler {
	@XmlElement(name = "tagging", required=true)
	private static List<Tagging> taggings = new ArrayList<Tagging>();

	public TaggingHandler() {

	}
	
	// GETTER
	/**
	 * Permet de recuperer tous les {@link Tagging Taggings} sous la forme d'une collection
	 * @return une {@link List} de {@link Tagging}
	 */
	public List<Tagging> getTaggings() {
		return taggings;
	}
	
	/**
	 * Methode qui permet d'acceder a une instance de {@link Tagging} a partir de son ID
	 * @param taggingId ID du {@link Tagging} a retrouver
	 * @return l'instance du {@link Tagging}
	 */
	public final Tagging getTaggingFromId(final String taggingId) {
		for(Tagging t : taggings){
			if(t.getId().equals(taggingId)) return t;
		}
		return null;
	}

	/**
	 * Permet de recuperer tous les {@link Tagging} qui associent un {@link Tag} a un ID de {@link Bookmark} donne.
	 * @param bmid l'ID du {@link Bookmark} recherche
	 * @return Collection de {@link Tagging Taggings} qui correspond
	 */
	public final List<Tagging> getTaggingsFromBookmarkId(final String bmid) {
		List<Tagging> tlist = new ArrayList<Tagging>();
		for(Tagging t : taggings){
			if(t.getBmId().equals(bmid)) tlist.add(t);
		}		
		return tlist;
	}
	
	/**
	 * Permet de recuperer tous les {@link Tagging} qui associent un {@link Bookmark} a un ID de {@link Tag} donne.
	 * @param tagid l'ID du {@link Tag} recherche
	 * @return Collection de {@link Bookmark Bookmarks} qui correspond
	 */
	public final List<Tagging> getTaggingsFromTagId(final String tagid) {
		List<Tagging> tlist = new ArrayList<Tagging>();
		for(Tagging t : taggings){
			if(t.getTagId().equals(tagid)) tlist.add(t);
		}		
		return tlist;
	}
	
	/**
	 * Permet de recuperer tous les {@link Tagging} crees par un {@link User} donne.
	 * @param userid l'ID du {@link User} recherche
	 * @return Collection de {@link Tagging} qui correspond
	 */
	public final List<Tagging> getTaggingsFromUserId(final String userid) {
		List<Tagging> tlist = new ArrayList<Tagging>();
		for(Tagging t : taggings){
			if(t.getAuthorId().equals(userid)) tlist.add(t);
		}		
		return tlist;
	}

	/**
	 * Creation d'un {@link Tagging}
	 * @param authorid ID de l'auteur
	 * @param bmid ID du {@link Bookmark}
	 * @param tagid ID du {@link Tag}
	 */
	public void createTagging(final String authorid, final String bmid, final String tagid){
		GregorianCalendar dateGreg = new GregorianCalendar();
		java.util.Date dateDate = dateGreg.getTime();		 

		DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-ddTHH:mm:ss.SSSZ");
		String datestr = dateFormat.format(dateDate);
		 
		taggings.add(new Tagging(datestr, authorid, bmid, tagid));
		Writer.serializeTaggings();
	}
	
	
	// REMOVE

	/**
	 * Suppression d'un {@link Tagging} dans le {@link TaggingHandler} a partir de son instance.
	 * @param t instance du {@link Tagging}
	 */
	public void removeTagging(final Tagging t){
		taggings.remove(t);
	}
	
	
	/**
	 * Supprime tous les {@link Tagging Taggings} associes a un {@link Bookmark} donne.  
	 * @param bmid ID du {@link Bookmark} recherche
	 */
	public final void removeTaggingsWithBookmarkId(final String bmid){
		List<Tagging> glist = getTaggingsFromBookmarkId(bmid);
		for(Tagging t : glist){
			taggings.remove(t);
		}
		Writer.serializeTaggings();
	}
	
	/**
	 * Supprime tous les {@link Tagging Taggings} associes a un {@link Tag} donne.  
	 * @param tagid ID du {@link Tag} recherche
	 */
	public final void removeTaggingsWithTagId(final String tagid){
		List<Tagging> glist = getTaggingsFromTagId(tagid);
		for(Tagging t : glist){
			taggings.remove(t);
		}
		Writer.serializeTaggings();
	}
	
	/**
	 * Supprime tous les {@link Tagging Taggings} crees par un {@link User} donne.  
	 * @param userid ID du {@link User} recherche
	 */
	public final void removeTaggingsWithUserId(final String userid){
		List<Tagging> glist = getTaggingsFromUserId(userid);
		for(Tagging t : glist){
			taggings.remove(t);
		}
		Writer.serializeTaggings();
	}

	// UPDATE
	
	/**
	 * Mise a jour de tous les {@link Tagging Taggings} suite a un changement d'ID de {@link Bookmark}.
	 * Etant donne que les ID de {@link Tagging Taggings} sont generes a partir des ID de {@link Bookmark}, 
	 * il est necessaire de mettre a jour non seulement la propriete <code>bmid</code> des {@link Tagging Taggings} mais aussi leurs ID.
	 * @param oldbmid ancien ID du {@link Bookmark}
	 * @param newbmid nouvel ID du {@link Bookmark}
	 */
	public final void updateTaggingsWithBookmarkId(final String oldbmid, final String newbmid){
		List<Tagging> glist = getTaggingsFromBookmarkId(oldbmid);
		for(Tagging t : glist){
			t.setBmId(newbmid);
		}
		Writer.serializeTaggings();
	}
	
	/**
	 * Mise a jour de tous les {@link Tagging Taggings} suite a un changement d'ID de {@link Tag}.
	 * Etant donne que les ID de {@link Tagging Taggings} sont generes a partir des ID de {@link Tag}, 
	 * il est necessaire de mettre a jour non seulement la propriete <code>bmid</code> des {@link Tagging Taggings} mais aussi leurs ID.
	 * @param oldtagid ancien ID du {@link Tag}
	 * @param newtagid nouvel ID du {@link Tag}
	 */
	public final void updateTaggingsWithTagId(final String oldtagid, final String newtagid){
		List<Tagging> glist = getTaggingsFromTagId(oldtagid);
		for(Tagging t : glist){
			t.setTagId(newtagid);
		}
		Writer.serializeTaggings();
	}
	
	/**
	 * Mise a jour de tous les {@link Tagging Taggings} suite a un changement d'ID de {@link Tag}.
	 * @param olduserid ancien ID du {@link User}
	 * @param newuserid nouvel ID du {@link User}
	 */
	public final void updateTaggingsWithUserId(final String olduserid, final String newuserid){
		List<Tagging> glist = getTaggingsFromUserId(olduserid);
		for(Tagging t : glist){
			t.setAuthorId(newuserid);
		}
		Writer.serializeTaggings();
	}
	
	/**
	 * Methode utilitaire pour afficher le nombre d'&eacute;l&eacute;ments contenus dans la liste.
	 */
	public void print(){
		System.out.print("=> "+taggings.size()+" éléments chargés\n");
	}	
}