package page.distribute;

import java.io.IOException;
import java.util.LinkedList;
import java.util.List;

import org.wikiwebserver.core.WareHouse;
import org.wikiwebserver.distribute.interfaces.Task;
import org.wikiwebserver.distribute.interfaces.WorkerNode;
import org.wikiwebserver.distribute.se.worker.task.DirectoryListingTask;
import org.wikiwebserver.distribute.server.TaskStub;
import org.wikiwebserver.distribute.util.FileDetails;
import org.wikiwebserver.distribute.util.PersistableVector;
import org.wikiwebserver.handler.http.HTTPException;
import org.wikiwebserver.handler.http.HTTPHandler;
import org.wikiwebserver.handler.http.interfaces.CacheableHTTPResponse;
import org.wikiwebserver.handler.http.interfaces.HTTPResponder;

import page.tools.entity.Browser;


public class AudioPlaylist implements HTTPResponder, CacheableHTTPResponse {
	
	private static final long DEFAULT_EXPIRE = 48 * 60 * 60 * 1000;
	
	private final WorkerNode node;
	private final String path;
	
	public AudioPlaylist(WorkerNode node, String path) {
		this.node = node;
		this.path = path;		
	}
	
	public void init(HTTPHandler conn) {
	    conn.getResponse().getHeaders().set("Content-Type", "application/xspf+xml");
	}
	
    public Object respond(HTTPHandler conn) throws IOException {
        
        String decodedPath = FileBrowser.decodePath(path);
        
		Task task = new DirectoryListingTask();
		task.setTaskInputMeta(decodedPath);
		
        String password = (String) Browser.getBrowser(conn).get("nodeTaskPassword");
        task.setTaskPassword(password);
		
		List<FileDetails> audioFiles = new LinkedList<FileDetails>();    		
		
		
		TaskStub stub;
        try {
            stub = node.addNewTaskAndWait(task);
        } catch (Exception ex) {
            String msg = "Failed to get directory listing from node";
            throw new HTTPException(500, msg, ex);
        }

		PersistableVector fileDetails = (PersistableVector) stub.getOutput();
		

		String title = decodedPath;
		int idx1 = decodedPath.lastIndexOf('/', title.length()-1);
		if (idx1 > 0) {
		    title = decodedPath.substring(idx1);
		}
		
		if (fileDetails == null) {
			throw new IOException("Node did not return a directory listing");
		}
		
		long largest = 0;
		String imageUrl = null;
		for (Object obj : fileDetails) {
			FileDetails item = (FileDetails) obj;
			if (!item.isDirectory()) {
                String type = WareHouse.getContentType(item.getName());				    
			    if (type.startsWith("audio/")) {
			        audioFiles.add(item);
			    }
			    if (type.startsWith("image/") &&
			        item.getName().startsWith("AlbumArt") && 
			        item.getLength() > largest) {
			        
			        String encName = WareHouse.urlEncode(item.getName());
			        imageUrl = conn.getServiceAddress() + conn.getRequest().getUrl() + encName;
			        largest = item.getLength();
			    }
			}
		}
		
		StringBuilder playlist = new StringBuilder();
		
        playlist.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
        playlist.append("<playlist version='1' xmlns='http://xspf.org/ns/0/'>");	
        
        playlist.append("<title>");
        playlist.append(WareHouse.escapeHTMLEntities(title));
        playlist.append("</title>");       
        
        playlist.append("<info>");
        playlist.append(conn.getServiceAddress() + conn.getRequest().getUrl());
        playlist.append("</info>");      
        
        playlist.append("<trackList>");         
		
		for (FileDetails item : audioFiles) {
		    String encName = WareHouse.urlEncode(item.getName());
		    String fullUrl = conn.getServiceAddress() + conn.getRequest().getUrl() + encName;

		    playlist.append("<track>");
		    
            playlist.append("<title>");
            playlist.append(WareHouse.escapeHTMLEntities(item.getName()));
            playlist.append("</title>");		
            
            playlist.append("<image>");
            playlist.append(imageUrl);
            playlist.append("</image>");                
		    
			playlist.append("<location>");
			playlist.append(fullUrl);
			playlist.append("</location>");
			
			playlist.append("</track>");
		}
		
        playlist.append("</trackList>");
        playlist.append("</playlist>");       
        
        return playlist.toString();

    }
  
    public String getCacheKey() {
        
    	// Don't cache failed node lookups
    	if (node == null) return null;
    	
    	StringBuilder key = new StringBuilder();
    	
    	key.append(node.getNodeId());
    	key.append(path);
    	key.append(node.getConfigurationId());
    	
    	return key.toString();
    }
    
    public long getExpireTime() {
        return System.currentTimeMillis() + DEFAULT_EXPIRE;
    }
}
