package me.moodcat.database.controllers;

import static me.moodcat.database.entities.QSong.song;

import java.util.List;

import javax.persistence.EntityManager;

import me.moodcat.database.embeddables.VAVector;
import me.moodcat.database.entities.Room;
import me.moodcat.database.entities.Song;

import com.google.inject.Inject;
import com.google.inject.persist.Transactional;
import com.mysema.query.types.expr.NumberExpression;

/**
 * Used to retrieve songs from the database.
 */
public class SongDAO extends AbstractDAO<Song> {

    private static final int AMOUNT_OF_SONGS = 5;
	private static final double VECTOR_DISTANCE_DELTA = 0.1;

    @Inject
    public SongDAO(final EntityManager entityManager) {
        super(entityManager);
    }

    /**
     * Get all the lists stored in the database.
     *
     * @return The list of songs stored in the database.
     */
    @Transactional
    public List<Song> listSongs() {
        return this.query().from(song)
                .list(song);
    }

    /**
     * Retrieve random unclassified songs from the database.
     *
     * @param limit
     *            The number of songs to retrieve.
     * @return A list of random songs.
     */
    @Transactional
    public List<Song> listRandomsongs(final int limit) {
        return query().from(song)
                .where(song.valenceArousal.location.distance(VAVector.ZERO.getLocation()).lt(VECTOR_DISTANCE_DELTA))
                .orderBy(NumberExpression.random().asc())
                .limit(limit)
                .list(song);
    }

    /**
     * Get a song by name.
     *
     * @param name
     *            The (case-ignored) name of the song.
     * @return The song, if found.
     */
    @Transactional
    public Song findByName(final String name) {
        return ensureExists(this.query().from(song)
            .where(song.name.equalsIgnoreCase(name))
            .singleResult(song));
    }

    /**
     * Get a song by id.
     *
     * @param id
     *            The id of song.
     * @return The song, if found.
     */
    @Transactional
    public Song findById(final int id) {
        return ensureExists(this.query().from(song)
                .where(song.id.eq(id))
                .singleResult(song));
    }

    /**
     * Get a song by SoundCloud id.
     *
     * @param id
     *            The SoundCloud id of the song.
     * @return The song, if found.
     */
    @Transactional
    public Song findBySoundCloudId(final int id) {
        return ensureExists(this.query().from(song)
                .where(song.soundCloudId.eq(id))
                .singleResult(song));
    }

    /**
     * Find songs for distance.
     *
     * @param vector
     *            Vector to search
     * @param limit
     *            limit of results
     * @return List of songs
     */
    @Transactional
    public List<Song> findForDistance(final VAVector vector, final long limit) {
        return query().from(song)
                .orderBy(song.valenceArousal.location.distance(vector.getLocation()).asc())
                .limit(limit)
                .list(song);
    }

    /**
     * Find songs for a room.
     * 
     * @param fetchingRoom
     * 			  Room to search for.
     * @return List of songs
     */
    @Transactional
    public List<Song> findNewSongsFor(final Room fetchingRoom) {
        return query().from(song)
            .where(song.exclusions.contains(fetchingRoom).not())
            .orderBy(song.valenceArousal.location.distance(fetchingRoom.getVaVector().getLocation()).asc())
            .limit(AMOUNT_OF_SONGS)
            .list(song);
    }

}

@@ -579,12 +579,17 @@
 S = 
+2
 5;%0A
-%09
+%0A    
 priv
@@ -1290,32 +1290,49 @@
   return query()
+%0A                
 .from(song)%0A    
@@ -1420,16 +1420,41 @@
 n()).lt(
+%0A                        
 VECTOR_D
@@ -1875,32 +1875,36 @@
 ng)%0A            
+    
 .where(song.name
@@ -1928,16 +1928,20 @@
 (name))%0A
+    
         
@@ -3250,11 +3250,17 @@
   * 
-%09%09%09
+         
   Ro
@@ -3412,32 +3412,49 @@
   return query()
+%0A                
 .from(song)%0A    
@@ -3441,32 +3441,36 @@
     .from(song)%0A
+    
             .whe
@@ -3522,32 +3522,36 @@
 ())%0A            
+    
 .orderBy(song.va
@@ -3535,32 +3535,57 @@
        .orderBy(
+%0A                        
 song.valenceArou
@@ -3606,16 +3606,49 @@
 istance(
+%0A                                
 fetching
@@ -3696,24 +3696,28 @@
             
+    
 .limit(AMOUN
@@ -3728,16 +3728,20 @@
 _SONGS)%0A
+    
         

Set amount of songs queried back to 25