import javax.xml.parsers.DocumentBuilderFactory
import javax.xml.xpath.XPathFactory

import org.w3c.dom.Element

import org.jdom.transform.JDOMResult.DocumentBuilder
import org.serviio.library.metadata.*
import org.serviio.library.online.*

/**
 * blip.tv content URL extractor plugin for serviio 
 * 
 * @author DizTortion
 */
class BlipTVUrlExtractor extends FeedItemUrlExtractor {
	/*
	 * http://blip.tv/<username>/rss
	 */
	final VALID_FEED_URL = 'http(s)?://blip\\.tv/(.+/)?rss(/)?'
	
	ContentURLContainer extractUrl(Map links, PreferredQuality requestedQuality) {
		String linkUrl = links.alternate != null ? links.alternate : links.default
		String contentUrl
		String thumbnailUrl

		String videoInfoUrl = linkUrl.toString();
		videoInfoUrl = videoInfoUrl.substring(0, videoInfoUrl.lastIndexOf('/')) + "/rss";
		
		Element videoInfoWebPage = getXmlDocument(new URL(videoInfoUrl).getText());

		thumbnailUrl = evaluateXPath(videoInfoWebPage, "/rss/channel/item[link='" + linkUrl + "']/thumbnail/@url")
		
		switch (requestedQuality)
		{
			case PreferredQuality.HIGH:
				contentUrl = evaluateXPath(videoInfoWebPage, "/rss/channel/item[link='" + linkUrl + "']/group/content[@role='Blip HD 720']/@url")
				
				if (!contentUrl.isEmpty())			
					break;
			
			case PreferredQuality.MEDIUM:
				contentUrl = evaluateXPath(videoInfoWebPage, "/rss/channel/item[link='" + linkUrl + "']/group/content[@role='Blip SD']/@url")
				
				if (!contentUrl.isEmpty())			
					break;
				
			case PreferredQuality.LOW:
				contentUrl = evaluateXPath(videoInfoWebPage, "/rss/channel/item[link='" + linkUrl + "']/group/content[@role='Blip LD']/@url")
				
				if (!contentUrl.isEmpty())			
					break;
				
			default:
				log("Quality setting '" + preferredQuality + "' is currently not supported, or the video uploader doesn't provide the requested quality for the current video. Falling back to source quality");
				contentUrl = evaluateXPath(videoInfoWebPage, "/rss/channel/item[link='" + linkUrl + "']/group/content[@role='Source']/@url")
				break;
		}

        return new ContentURLContainer(fileType: MediaFileType.VIDEO, contentUrl: contentUrl, thumbnailUrl: thumbnailUrl)
	}
	
	Element getXmlDocument(String xml)
	{
		javax.xml.parsers.DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder()
		ByteArrayInputStream inputStream = new ByteArrayInputStream(xml.bytes)
		return builder.parse(inputStream).documentElement
	}
	
	String evaluateXPath(org.w3c.dom.Element videoInfoWebPage, String xPathQuery)
	{
		def xpath = XPathFactory.newInstance().newXPath();
		return xpath.evaluate(xPathQuery, videoInfoWebPage)
	}

	boolean extractorMatches(URL feedUrl) {
		return feedUrl ==~ VALID_FEED_URL
	}

	String getExtractorName() {
		return getClass().getName()
	}
	
    static void main(args) {
    	BlipTVUrlExtractor extractor = new BlipTVUrlExtractor();
    	
       	assert extractor.extractorMatches(new URL("http://blip.tv/day9tv/rss"));
		assert extractor.extractorMatches(new URL("http://blip.tv/day9tv/rss/"));
    	assert extractor.extractorMatches(new URL("https://blip.tv/day9tv/rss"));
    	assert extractor.extractorMatches(new URL("https://blip.tv/day9tv/rss/"));
    	assert !extractor.extractorMatches(new URL("http://blip1.tv/rss"));
    	assert !extractor.extractorMatches(new URL("http://blip1.tv/rss/"));
    	assert !extractor.extractorMatches(new URL("https://blip1.tv/rss"));
    	assert !extractor.extractorMatches(new URL("https://blip1.tv/rss/"));

    	Map links = ['alternate': new URL('http://blip.tv/redlettermedia/half-in-the-bag-ep-11-transformers-3-5389847')] 
    	extractor.extractUrl(links, PreferredQuality.HIGH);
    }
}
