package controller;

import java.util.ArrayList;
import java.util.regex.Pattern;

import org.bson.types.ObjectId;

import model.Film;
import businessUtils.DbConnection;
import businessUtils.Fonctions;

import com.mongodb.BasicDBList;
import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;

public class DbController {
	final static DBCollection coll = DbConnection.getDB().getCollection("films");
	
	/**
	 * getFilms()
	 * Fonction qui renvoit l'ensemble des films de la base de données
	 * @return films
	 */
	public static ArrayList<Film> getFilms(){
		final DBCursor results = coll.find().sort(new BasicDBObject("titre", 1));
		ArrayList<Film> films = new ArrayList<>();
		while (results.hasNext()) {
		    final DBObject dbObject = results.next();
		    final Object id = dbObject.get("_id");
		    final Object titre = dbObject.get("titre");
		    final Object annee = dbObject.get("annee");
		    final Object note = dbObject.get("note");
		    final Object nbVotant = dbObject.get("nbVotant");
		    //gestion de plusieurs occurences dans le champ genre
		    ArrayList<String> genreArr = new ArrayList<>();
		    genreArr = Fonctions.fillArray(dbObject.get("genre"), genreArr);
		    
		    ArrayList<String> natioArr = new ArrayList<>();
		    natioArr = Fonctions.fillArray(dbObject.get("natio"), natioArr);
		    
		    Film f = new Film();
		    f.setId(id.toString());
		    f.setTitre(titre.toString());
		    if(annee == null){
		    	f.setAnnee("");
		    } else {
		    	f.setAnnee(annee.toString().substring(0, 4));
		    }
		    if(genreArr.size() == 0){
		    	f.setGenre("");
		    } else {
				f.setGenre(Fonctions.parseArray(genreArr));
		    }  
		    if(natioArr.size() == 0){
		    	f.setNatio("");
		    } else {
		    	f.setNatio(Fonctions.parseArray(natioArr));
		    }    
		    if(note == null){
		    	f.setNote(0);
		    } else {
		    	f.setNote(Double.parseDouble(note.toString()));
		    }
		    if(nbVotant == null){
		    	f.setNbVotant(0);
		    } else{
		    	f.setNbVotant((int) nbVotant);
		    }
		    films.add(f);
		}
	    return films;
	}
	
	/**
	 * getFilmById(String id)
	 * Fonction qui retourne une liste de film selon l'id en paramètre
	 * @param id
	 * @return f
	 */
	public static Film getFilmById(String id){
		DBObject searchById = new BasicDBObject("_id", new ObjectId(id));
		DBObject film = coll.findOne(searchById);
		
		Film f = new Film();
		f.setId(id);
		f.setTitre(film.get("titre").toString());
		if(film.get("note") == null){
			f.setNote(0);
		} else{
			f.setNote(Double.parseDouble(film.get("note").toString()));
		}
		if(film.get("nbVotant") == null){
			f.setNbVotant(0);
		} else{
			f.setNbVotant((int) film.get("nbVotant"));
		}	
		if(film.get("annee") == null){
	    	f.setAnnee("");
	    } else {
	    	f.setAnnee(film.get("annee").toString().substring(0, 4));
	    }
		ArrayList<String> genreArr = new ArrayList<>();
		genreArr = Fonctions.fillArray(film.get("genre"), genreArr);
	    if(genreArr.size() == 0){
	    	f.setGenre("");
	    } else {
			f.setGenre(Fonctions.parseArray(genreArr));
	    }
		ArrayList<String> natioArr = new ArrayList<>();
	    natioArr = Fonctions.fillArray(film.get("natio"), natioArr);
	    if(natioArr.size() == 0){
	    	f.setNatio("");
	    } else {
			f.setNatio(Fonctions.parseArray(natioArr));
	    } 
	    return f;	    
	}
	
	/**
	 * getByTitre(String title)
	 * Fonction qui retourne une liste de film selon le titre en paramètre
	 * @param title
	 * @return films
	 */
	public static ArrayList<Film> getByTitre(String title){
		BasicDBObject query = new BasicDBObject();
		Pattern regex = Pattern.compile(title, Pattern.CASE_INSENSITIVE); 
		query.put("titre", regex);
		
		final DBCursor results = coll.find(query);
		ArrayList<Film> films = new ArrayList<>();
		while (results.hasNext()) {
		    final DBObject dbObject = results.next();
		    final Object titre = dbObject.get("titre");
		    final Object annee = dbObject.get("annee");
		    ArrayList<String> genreArr = new ArrayList<>();
		    genreArr = Fonctions.fillArray(dbObject.get("genre"), genreArr);
		    ArrayList<String> natioArr = new ArrayList<>();
		    natioArr = Fonctions.fillArray(dbObject.get("natio"), natioArr);
		    
		    Film f = new Film();
		    f.setTitre(titre.toString());
		    if(annee == null){
		    	f.setAnnee("");
		    } else {
		    	f.setAnnee(annee.toString().substring(0, 4));
		    }
		    if(genreArr.size() == 0){
		    	f.setGenre("");
		    } else {
				f.setGenre(Fonctions.parseArray(genreArr));
		    }  
		    if(natioArr.size() == 0){
		    	f.setNatio("");
		    } else {
				f.setNatio(Fonctions.parseArray(natioArr));
		    }    
		    films.add(f);
		}
		return films;
	}
	
	/**
	 * addFilm(String titre, String annee, String[] genreArr, String[] natioArr)
	 * Cette méthode permet d'ajouter un film dans la base de données
	 * @param titre
	 * @param annee
	 * @param genreArr
	 * @param natioArr
	 */
	public static void addFilm(String titre, String annee, String[] genreArr, String[] natioArr){	
		BasicDBObject film = new BasicDBObject();
		film.put("titre", titre);
		film.put("annee", Integer.parseInt(annee));
		film.put("genre", Fonctions.arrayToBDBL(genreArr));
		film.put("natio", Fonctions.arrayToBDBL(natioArr));
		coll.insert(film);
	}
	
	public static void editFilm(Film f){
		BasicDBObject film = new BasicDBObject();
		film.put("titre", f.getTitre());
		film.put("annee", f.getAnnee());
		film.put("genre", f.getGenreArr());
		film.put("natio", f.getNatioArr());
		
		BasicDBObject updateObj = new BasicDBObject();
	    updateObj.put("$set", film);
		BasicDBObject searchQuery = new BasicDBObject("_id", new ObjectId(f.getId()));
		coll.update(searchQuery, updateObj);
	}
	
	public static void deleteFilm(String id){
		coll.remove(new BasicDBObject().append("_id", new ObjectId(id)));
	}
	
	public static void addVote(String id, double note){
		Film f = DbController.getFilmById(id);
		BasicDBObject film = new BasicDBObject();
		
		if(f.getNote() == 0 || f.getNbVotant() == 0){
			film.put("note", note);
			film.put("nbVotant", 1);
		} else {
			int updateVotant = f.getNbVotant() + 1;
			double updatedNote = note + f.getNote();
			film.put("note", updatedNote);
			film.put("nbVotant", updateVotant);
		}
		BasicDBObject updateObj = new BasicDBObject();
	    updateObj.put("$set", film);
		BasicDBObject searchQuery = new BasicDBObject("_id", new ObjectId(f.getId()));
		coll.update(searchQuery, updateObj);
	}
		
}
