import groovy.json.JsonSlurper
import org.serviio.library.metadata.*
import org.serviio.library.online.*
import org.serviio.util.*

/**
 * WebResource extractor plugin for hd-trailers.net.
 * 
 * @author jhb50
 * Version 1 - July 20, 2012
 *
 * Usage:
 *  http://rage.d14n.org/playlist/snnnnnnn for a rage playlist
 *  or
 *  http://rage.d14n.org/playlist/ for most recent rage playlist
 * 
 *  with optional parameters
 *  for resolution res=nnnn where nnnn = 1080, 720, 480, 360, 240
 *    default is console quality value
 *  for starting video start=nnn where nnn=1 to 999
 *    default is 1
 */
class Rage extends WebResourceUrlExtractor {
	
	final VALID_FEED_URL = '^http://rage.d14n.org/playlist/.*?'
	
	String getExtractorName() {
		return 'Rage'
	}
	
	Boolean URLExists(URL fileURL){
		if(((HttpURLConnection) fileURL.openConnection()).getResponseCode() == 404){
			return false
		}
		return true
	}

	boolean extractorMatches(URL feedUrl) {
		return feedUrl ==~ VALID_FEED_URL
	}
	
	WebResourceContainer extractItems(URL resourceUrl, int maxItems) {
		List<WebResourceItem> items = []
		def itemsAdded = 0
		String rootUrl = resourceUrl
		String html
		String pageTitle = ""
		String pageThumb = ""
		String videoUrl = ""
		String videoTitle = ""
		String thumbUrl = ""
		Short Start = 0 
		Short Res = 0
		Short itemNum = 0
		def playlist = false
		
		def parmMatcher = resourceUrl =~ '^http://rage.d14n.org/playlist/(.*?)\\?.*?'
		def parmMatch = resourceUrl ==~ '^http://rage.d14n.org/playlist/.+?\\?.*?'
		if (parmMatch){
			rootUrl = "http://rage.d14n.org/playlist/" + parmMatcher[0][1].trim()
			playlist = true
		}
		else{
			parmMatcher = resourceUrl =~ '^http://rage.d14n.org/playlist/([0-9A-Za-z_-]+)'
			parmMatch = resourceUrl ==~ '^http://rage.d14n.org/playlist/[0-9A-Za-z_-]+'
			if (parmMatch){
				rootUrl = "http://rage.d14n.org/playlist/" + parmMatcher[0][1]
				playlist = true
			}
		}
		
		parmMatcher = resourceUrl =~ '^http://rage.d14n.org.*?res=([0-9]+)'
		parmMatch = resourceUrl ==~ '^http://rage.d14n.org.*?res=[0-9]+.*?'
		if (parmMatch){
			Res = parmMatcher[0][1].trim().toShort() 
			if(Res != 1080 && Res != 720 && Res != 360 && Res != 240) Res = 480
		}
		
		parmMatcher = resourceUrl =~ '^http://rage.d14n.org.*?start=([0-9]+)'
		parmMatch = resourceUrl ==~ '^http://rage.d14n.org.*?start=[0-9]+.*?'
		if (parmMatch){
			Start = parmMatcher[0][1].trim().toShort() - 1
			if(Start < 0) Start = 0
		}

		if (playlist == false){
			html = new URL("http://rage.d14n.org").getText()
			def playlistMatcher = html =~ '(?s)<a href="/playlist/(.*?)".*?'
			rootUrl = "http://rage.d14n.org/playlist/" + playlistMatcher[0][1]
		}
		
		if (!URLExists(new URL(rootUrl))){
			log ("404 for $rootUrl")
			return null
		}

		html = new URL(rootUrl).getText()

		def titleMatcher = html =~ '(?s)<title>(.*?)</title>.*?'
		pageTitle = titleMatcher[0][1].trim()
		println "\npagetitle = $pageTitle"
		
		if (html.count("'key':") >= Start ){
			
			def videoMatcher = html =~ '(?s).*?key(.*?)}'

			for( int i = Start; i < (html.count("'key':")+ Start) && (maxItems == -1 || itemsAdded < maxItems); i++ ) {
				def videoGetMatcher = videoMatcher[i][0]  =~ '(?s).*?name.*?"(.*?)".*?video_id\'.*?\'(.*?)\'.*?thumbnail\'.*?\'(.*?)\'.*?'
				def videoGetMatch = videoMatcher[i][0]  ==~ '(?s).*?name.*?".*?".*?video_id\'.*?\'.*?\'.*?thumbnail\'.*?\'.*?\'.*?'
				if(videoGetMatch){
					videoUrl = "http://www.youtube.com/watch?v=" + videoGetMatcher[0][2].trim()
					
					itemNum = i + 1 
					
					videoTitle = "[" + itemNum + "] " + videoGetMatcher[0][1].trim()
					
					thumbUrl = videoGetMatcher[0][3].trim()

					WebResourceItem item = new WebResourceItem(title: videoTitle, additionalInfo: ['videoUrl':videoUrl,'thumbUrl':thumbUrl,'Res': Res])
					
					items << item
					itemsAdded++
				}
			}
		}	
	 	return new WebResourceContainer(title: pageTitle, thumbnailUrl: pageThumb, items: items)
	}

	
	ContentURLContainer extractUrl(WebResourceItem item, PreferredQuality requestedQuality) {		
		
		String videoTitle = item.title
		String videoUrl = item.getAdditionalInfo()['videoUrl']
		String thumbUrl = item.getAdditionalInfo()['thumbUrl']
		Short Res = item.getAdditionalInfo()['Res']
		
		String linkUrl = ""
		String thumbnailUrl = ""
		String UserAgent = ""
		
		String videohtml = new URL(videoUrl).getText()
		def flashMatch = videohtml ==~ '(?s).*?url_encoded_fmt_stream_map=.*?'
		if (!flashMatch){
			log("NO ENTRIES FOR THIS ITEM - \'$videoTitle\'") 
			return null
		}

		String videostart = videohtml.minus(~'(?s).*?url_encoded_fmt_stream_map=.*?')
		String videolinks = videostart.replaceFirst(~'(?s).u0026amp.*?</html>',"")+"%2C"
		
		def videoMatcher = videolinks =~ '(?s).*?url%3D(.*?)itag%253D(.*?)%25(.*?)%26quality'
		
		for( int i = 0; i < videoMatcher.size(); i++ ) {
			String Formats  = "37, 22, 35, 18, 34, 6, 5"
			String fmt
			String itag
			if (Res == 0){
				if (requestedQuality == PreferredQuality.MEDIUM) Formats  = "35, 18, 34, 6, 5"
				else
				if (requestedQuality == PreferredQuality.LOW) Formats  = "6, 5"
			}
			else
			if (Res == 720) Formats  = "22, 35, 18, 34, 6, 5"
			else
			if (Res == 480) Formats  = "35, 18, 34, 6, 5"
			else
			if (Res == 360) Formats  = "18, 34, 6, 5"
			else
			if (Res == 240) Formats  = "6, 5"

			itag = videoMatcher[i][2].trim()
			if (Formats.contains(itag)) {
				linkUrl = videoMatcher[i][1].trim()+"itag%253D"+videoMatcher[i][2].trim()+"%25"+videoMatcher[i][3].trim()
				linkUrl = URLDecoder.decode(linkUrl)
				linkUrl = URLDecoder.decode(linkUrl)
				linkUrl = URLDecoder.decode(linkUrl)
				break  
			}
		}
		
		log("Getting item: $videoTitle")

		linkUrl = linkUrl.replaceAll("&amp;","&")
		
		def cacheKey = videoUrl  + "_" +  Res
	
		return new ContentURLContainer(fileType: MediaFileType.VIDEO, contentUrl: linkUrl, thumbnailUrl: thumbUrl, cacheKey: cacheKey, expiresImmediately: true)
	}
	
	static void main(args) {
		Rage extractor = new Rage()
				
		assert extractor.extractorMatches( new URL("http://rage.d14n.org/playlist/s3540478") )
		assert !extractor.extractorMatches( new URL("http://google.com/feeds/api/standardfeeds/top_rated?time=today") )
		//WebResourceContainer container = extractor.extractItems( new URL("http://rage.d14n.org/playlist/s3540478?start=21"), 12)    
		WebResourceContainer container = extractor.extractItems( new URL("http://rage.d14n.org/?res=240&start=10"), 12)    
		//WebResourceContainer container = extractor.extractItems( new URL("http://rage.d14n.org/playlist/"), 12)    
		println container
		
		ContentURLContainer result = extractor.extractUrl(container.getItems()[3], PreferredQuality.HIGH)
		print "result = $result"
	}
}
