package model;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
import controller.PhoenixCore;
import controller.QuickTrackSort;
import controller.threads.PlaylistRowReorderer;
/**
* Stellt die Bibliothek dar
*
* @author Artur Dawtjan
*
*/
public class Library{
List<Artist> artists = null;
List<Album> albums = null;
List<Track> tracks = null;
PreparedStatement checkStmt = null;
PreparedStatement checkPlaylistStmt = null;
private int playlistID = -1;
/**
* Dieser konstruktor initialisiert die library mit den dem kompletten datenbestand aus der DB
* @param loadLibFromDB true, wenn die Lib aus der DB geladen werden soll, false wenn leere lib benötigt wird (z.B. Queue mode)
*/
public Library(boolean loadLibFromDB) {
if (!loadLibFromDB) {
tracks= new ArrayList<Track>();
return;
}
artists = new ArrayList<Artist>();
albums = new ArrayList<Album>();
tracks = new ArrayList<Track>();
try {
checkStmt = PhoenixCore.DBCON.prepareOnLib("update tracks set checked=? where id=?");
checkPlaylistStmt = PhoenixCore.DBCON.prepareOnLib("update playlist_track set checked=? where listid=? and trackid=?");
} catch (SQLException e) {
e.printStackTrace();
}
loadFromDB("select t.id, t.name, ar.id as artistID, t.album as albumID, t.genre, t.track, t.length, "
+ "t.checked, t.path, ar.name as artistName, al.name as albumName from tracks t "
+ "inner join albums al on t.album=al.id inner join artists ar on al.artist=ar.id order by lower(artistName), lower(albumName), t.track asc");
}
/**
* Konstruktor für eine lib, die eine playlist enthält. diese wird anhand der playlistID aus der DB gezogen
*@param playlistID
* @param playlistName
*/
public Library(int playlistID, String playlistName) {
artists = new ArrayList<Artist>();
albums = new ArrayList<Album>();
tracks = new ArrayList<Track>();
try {
checkStmt = PhoenixCore.DBCON.prepareOnLib("update tracks set checked=? where id=?");
checkPlaylistStmt = PhoenixCore.DBCON.prepareOnLib("update playlist_track set checked=? where listid=? and trackid=?");
} catch (SQLException e) {
e.printStackTrace();
}
this.playlistID = playlistID;
// loadFromDB("select t.id, t.name, ar.id as artistID, t.album as albumID, t.genre, " +
// "t.track, t.length, pt.checked, t.path, ar.name as artistName, al.name as albumName " +
// "from playlist_track pt inner join tracks t on t.id=pt.trackid inner join albums al on t.album=al.id " +
// "inner join artists ar on al.artist=ar.id where pt.listid="+playlistID+" order by pt.running_order asc");
loadFromDB("select t.id from playlist_track pt inner join tracks t on " +
"t.id=pt.trackid inner join albums al on t.album=al.id " +
"inner join artists ar on al.artist=ar.id where pt.listid="+playlistID+
" order by pt.running_order asc");
}
/**
* initialisiert die Lib mit den übergebenen tracks.
* @param trackList
*/
public Library(List<Track> trackList) {
tracks = trackList;
}
/**
* lädt den initialstand der DB
*/
private void loadFromDB(String query) {
// tracks importieren
ResultSet rs = PhoenixCore.DBCON
.executeOnLib(query);
try {
tracks.clear();
if (this.playlistID>0) {
while (rs.next()) {
tracks.add(new PlaylistTrack(rs.getInt("id"), this.playlistID));
}
}else {
while (rs.next()) {
tracks.add(new Track(rs.getInt("id")));
}
}
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
// alben importieren
rs = PhoenixCore.DBCON.executeOnLib("select id, name from albums order by lower(name) asc");
try {
while (rs.next()) {
albums.add(new Album(rs.getInt("id"), rs.getString("name")));
}
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
// artists importieren
rs = PhoenixCore.DBCON.executeOnLib("select id, name from artists order by lower(name) asc");
try {
while (rs.next()) {
artists.add(new Artist(rs.getInt("id"), rs.getString("name")));
}
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
public Track getTrackAt(int index){
if (index <0 && 0<getTrackCount()) {
return tracks.get(0);
}
return tracks.get(index);
}
public int getTrackCount() {
return tracks.size();
}
public int indexOf(Track t){
return tracks.indexOf(t);
}
public List<Track> getTracks() {
return tracks;
}
/**
* Holt den index-ten track aus der liste und entfernt diesen gleich
* @return den index-ten Track der liste. ist die liste leer, gibts null zurueck
*/
public Track pullTrack(int index){
if (tracks.size()<1) {
return null;
}
Track t = getTrackAt(index);
tracks.remove(index);
return t;
}
/**
* setzt das abspiel-flag und schreibt die änderung in die DB
* @param value neuer wert für flag
* @param trackID id aus der DB
* @param index in der lib
*/
public void setChecked(boolean value, int trackID, int index) {
try {
if (playlistID==-1) {
checkStmt.setBoolean(1, value);
checkStmt.setInt(2, trackID);
checkStmt.execute();
}else {
checkPlaylistStmt.setBoolean(1, value);
checkPlaylistStmt.setInt(2, playlistID);
checkPlaylistStmt.setInt(3, trackID);
checkPlaylistStmt.execute();
}
getTrackAt(index).setChecked(value);
Runtime.getRuntime().gc();
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* Liefert die artists als array
* @return array aus Artists
*/
public Artist[] getArtists() {
if (artists==null) {
return new Artist[]{};
}
return artists.toArray(new Artist[artists.size()]);
}
/**
* Liefert die artists als array
* @return array aus Artists
*/
public Album[] getAlbums() {
if (albums==null) {
return new Album[]{};
}
return albums.toArray(new Album[albums.size()]);
}
/**
* Setzt die Liste von Tracks
* @param tracks liste
*/
public void setTracks(List<Track> tracks) {
this.tracks = tracks;
if (currentSortDirection>0) {//ist eine zu sortierende richtung da,
//soll nach dieser sortiert werden
if (currentSortedColumn!=TrackTableModel.COL_ARTIST||currentSortDirection==TrackTableModel.SORT_DESC) {
char temp = currentSortedColumn;
currentSortedColumn = TrackTableModel.COL_ARTIST;
sort(temp, currentSortDirection);//nach ursprünglich sortierter column sortieren
}
}
}
/**
* fuegt das Track[] am ende hinzu
* @param tracks
*/
public void addTracks(Track[] tracks) {
for (int i = 0; i < tracks.length; i++) {
this.tracks.add(tracks[i]);
}
}
/**
* ordnet lib um, ein eintrag wird dabei hoch oder runtergeschoben.
* @param fromIndex
* @param toIndex
*/
public void reorder(int fromIndex, int toIndex) {
if (fromIndex+1==toIndex) {
return; //kein echtes verschieben...
}
if (playlistID!=-1) {//falls playlist-lib
//sortieren in der db anstoßen
Thread reorderInDB = new Thread(new PlaylistRowReorderer(getTrackCount(), playlistID, fromIndex, toIndex));
reorderInDB.start();
}
//und in der liste sortieren
Track fromTrack = tracks.get(fromIndex);
if (fromIndex<toIndex) {//nach unten verschoben...
for (int i = fromIndex; i < toIndex-1; i++) {
tracks.set(i, tracks.get(i+1));
}
tracks.set(toIndex-1, fromTrack);
}else {//nach oben verschoben...
for (int i = fromIndex; i > toIndex-1&&i>0; i--) {
tracks.set(i, tracks.get(i-1));
}
tracks.set(toIndex, fromTrack);
}
}
public int size() {
return tracks.size();
}
private char currentSortedColumn = TrackTableModel.COL_ARTIST;
private char currentSortDirection=TrackTableModel.SORT_ASC;
public void sort(char columnConstant, char sortDirection) {
if (tracks.size()<1) {
return;
}
currentSortDirection=sortDirection;
if (currentSortedColumn!=columnConstant) {//noch nicht sortiert?
QuickTrackSort.sort(this, columnConstant);//dann tu das
currentSortedColumn=columnConstant;
if (sortDirection==TrackTableModel.SORT_DESC) {//möglicherweise alte sortierung beibehalten
Collections.reverse(tracks);
}
}else {//schon sortiert
//dann nur invertieren
Collections.reverse(tracks);
}
}
public void setTrackAt(int i, Track trackAt) {
tracks.set(i, trackAt);
}
public void setPlaylistID(int id){
this.playlistID = id;
}
public void quickSearch(String text) {
// TODO quicksearch durch datenbank realisieren
if (text.length()==0) {loadFromDB("select t.id, t.name, ar.id as artistID, t.album as albumID, t.genre, t.track, t.length, "
+ "t.checked, t.path, ar.name as artistName, al.name as albumName from tracks t "
+ "inner join albums al on t.album=al.id inner join artists ar on al.artist=ar.id order by lower(artistName), lower(albumName), t.track asc");
} else if(text.length()>2){
loadFromDB("select t.id, t.name, ar.id as artistID, t.album as albumID, t.genre, t.track, t.length, "
+ "t.checked, t.path, ar.name as artistName, al.name as albumName from tracks t "
+ "inner join albums al on t.album=al.id inner join artists ar on al.artist=ar.id where t.name like '%"+text+"%' " +
"or albumName like '%"+text+"%' or artistName like '%"+text+"%' order by lower(artistName), lower(albumName), t.track asc");
}
}
public void removeTrackAt(int i) {
tracks.get(i).deleteFromDB();
tracks.remove(i);
}
public void shuffle() {
Random rand = new Random(System.nanoTime());
List<Track> trks = new ArrayList<Track>();
int idx;
while(tracks.size()>0) {
idx = rand.nextInt(tracks.size());
trks.add(tracks.get(idx));
tracks.remove(idx);
}
tracks = trks;
System.gc();
}
}