import org.serviio.library.metadata.*
import org.serviio.library.online.*
import org.serviio.util.*

/**
 * Content URL extractor plugin for CNN video feeds
 *
 * @author Petr Nejedly
 *
 */
class CNN extends FeedItemUrlExtractor {
	
	final VALID_FEED_URL = '^http(s)*://rss.cnn.com/.*$'
	
	String getExtractorName() {
		return 'CNN'
	}
	
	boolean extractorMatches(URL feedUrl) {
		return feedUrl ==~ VALID_FEED_URL
	}
	
	ContentURLContainer extractUrl(Map links, PreferredQuality requestedQuality) {
		def linkUrl = links.default
		def contentUrl
		def thumbnailUrl
		
		String videoInfoRelUrl = null
		
		try {
			if(linkUrl.toString().contains('/video')) {			
				def videoInfoUrlMatcher = linkUrl =~ '(?s)#/video/(.*?)(\\?.*)?$'
				videoInfoRelUrl = '/video/' + videoInfoUrlMatcher[0][1]
			} else {
				String pageHtml = linkUrl.getText()
				def videoInfoUrlMatcher = pageHtml =~ "(?s)cnnLoadStoryPlayer\\('(.*?)'"
				videoInfoRelUrl = '/video/' + videoInfoUrlMatcher[0][1]
			}
		} catch (Exception e) {
			log("Could not retrieve video information, possibly ther is no video on the page")
			return null
		}
		// get video info URL
		String videoInfoUrl = "http://edition.cnn.com/video/data/3.0${videoInfoRelUrl}/index.xml"
		// parse video info XML
		def videoNode = new XmlParser().parse( videoInfoUrl )
		contentUrl = getContentUrl(videoNode, requestedQuality)
		return new ContentURLContainer(contentUrl: contentUrl)		
	}
	
	def String getContentUrl(Node videoNode, PreferredQuality requestedQuality) {
		List groupFilesNode = videoNode.files.groupFiles
		List mediaItems = groupFilesNode.file
		if(mediaItems.size() >= 1 ) {
			if(mediaItems.get(0).text().endsWith('smil')) {
				// reference to a smil document
				def smilNode = new XmlParser().parse( mediaItems.get(0).text() )
				List fileNodes = smilNode.body.switch.video
				List sortedItems = fileNodes.sort { it.'@system-bitrate'.toInteger() }
				Node selectedMediaItem = findSuitableItem(sortedItems, requestedQuality)
				Node baseUrlNode = smilNode.head.meta.find { it.'@name' == 'httpBase'}				
				return "${baseUrlNode.'@content'}${selectedMediaItem.'@src'}"
			} else {
				// this might now be obsolete, looks like smil reference is always used
				List sortedItems = mediaItems.sort { it.'@bitrate'.toInteger() }
				Node selectedMediaItem = findSuitableItem(sortedItems, requestedQuality)
				return "${groupFilesNode.baseUrl.text()}${selectedMediaItem.text()}"
			}
		}
		return null
	}
	
	def Node findSuitableItem(List items, PreferredQuality requestedQuality) {
		if(requestedQuality == PreferredQuality.LOW) {
			// worst quality, get the first from the list
			return items.head()
		} else if (requestedQuality == PreferredQuality.MEDIUM) {
			// get item from the middle
			return items.get(Math.floor(items.size()/2).toInteger())
		} else {
			// best quality, take the last url
			return items.last()
		}
	}
	
	static void main(args) {
		// this is just to test
		CNN extractor = new CNN()
		
		assert extractor.extractorMatches( new URL("http://rss.cnn.com/rss/edition.rss") )
		assert !extractor.extractorMatches( new URL("http://google.com/feeds/api/standardfeeds/top_rated?time=today") )
		
		Map videoLinks = ['default': new URL('http://edition.cnn.com/video/#/video/world/2012/06/16/wr-china-space-launch.cnn?eref=edition')]
		ContentURLContainer result = extractor.extractUrl(videoLinks, PreferredQuality.MEDIUM)
		println "Result: $result"		 
		
		Map videoLinks2 = ['default': new URL('http://edition.cnn.com/2012/06/18/sport/tennis/tennis-nalbandian-police-assault/index.html?eref=rss_topstories&utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+rss%2Fcnn_topstories+%28RSS%3A+Top+Stories%29')]
		ContentURLContainer result2 = extractor.extractUrl(videoLinks2, PreferredQuality.MEDIUM)
		println "Result: $result2"
		
		Map videoLinks3 = ['default': new URL('http://edition.cnn.com/video/?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3A+rss%2Fcnn_topstories+%28RSS%3A+Top+Stories%29#/video/bestoftv/2012/04/20/exp-get-real-dating-spreadsheet.cnn?eref=rss_topstories')]
		ContentURLContainer result3 = extractor.extractUrl(videoLinks3, PreferredQuality.MEDIUM)
		println "Result: $result3"

	}
}