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  7, 2012
 * Version 2 - July  9, 2012 - add Apple Quicktime support for Serviio V1.0
 * Version 3 - July 30, 2012 - add Preference option for apple
 * Version 4 - Aug.  3, 2012 - display latest of anything if no trailers or teasers
 * Version 5 - Aug. 13, 2102 - add version logging & Version 1 prereq.
 * Version 6 - Sep. 17, 2012 - Exclude Restricted "Red Band Trailers"
 * Version 7 - Sep. 20, 2012 - Update for revised YouTube Links
 * Version 8 - Nov. 13, 2012 - Remove &amp; from Titles
 * Version 9 - Feb.  3, 2013 - New yahoo format
 * Version 10 - Mar.13, 2013 - Fix Thumbnail & Titles
 * Version 11 - May 19, 2013 - Use Prot read
 *
 * Usage:
 * Latest trailers:  	http://www.hd-trailers.net?start=nn&res=yyy
 * Most watched: 	http://www.hd-trailers.net/most-watched?res=yyy
 * Top 10:		http://www.hd-trailers.net/top-movies?res=yyy
 * Opening-this-week:	http://www.hd-trailers.net/opening-this-week?res=yyy
 * Coming soon:		http://www.hd-trailers.net/coming-soon?res=yyy
 * Netflix-new-releases http://www.hd-trailers.net/netflix-new-releases?res=yyy
 *
 * where start=1 to start=2700 & res=480, 720 or 1080 ; default = 480
 *
 */
class HDTrailers extends WebResourceUrlExtractor {
	
	final VALID_FEED_URL = '^http://www\\.hd-trailers\\.net.*?'
	
	String getExtractorName() {
		return 'HDTrailers'
	}
	boolean extractorMatches(URL feedUrl) {
		return feedUrl ==~ VALID_FEED_URL
	}

	int getVersion() {
		return 11
	}
	
	Boolean URLExists(String srcURL){
		URL fileURL = new URL(srcURL);
		if(((HttpURLConnection) fileURL.openConnection()).getResponseCode() == 404){
			return false
		}
		return true
	}
	String OpenProtURL(	String srcURL,	String Referrer	) {        

		def rv = ""
		URL url = new URL(srcURL);
		URLConnection conn = url.openConnection();
		conn.setRequestProperty("Referer", Referrer);
		conn.setRequestProperty("User-Agent","Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.83 Safari/537.1");
		conn.setRequestProperty("Accept-Language","en-US");
		conn.setDoOutput(true);

		BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
		String line;
		while ((line = rd.readLine()) != null) {
			rv += line
		}
		rd.close();        
        return rv
    }
	
	WebResourceContainer extractItems(URL resourceUrl, int maxItems) {

		log("Parsing with HDTrailers V${getVersion()}")

		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 Codec = 264
		Short Page = 1
		Short Plus = 0
		Short StartTrailer
		String Pref = ""

		def parmMatcher = resourceUrl =~ '^http://www\\.hd-trailers\\.net(.*?)\\?.*?'
		def parmMatch = resourceUrl ==~ '^http://www\\.hd-trailers\\.net.*?\\?.*?'
		if (parmMatch){
			rootUrl = "http://www.hd-trailers.net" + parmMatcher[0][1].trim()
		}
		
		parmMatcher = resourceUrl =~ '^http://www\\.hd-trailers\\.net.*?res=([0-9]+)'
		parmMatch = resourceUrl ==~ '^http://www\\.hd-trailers\\.net.*?res=[0-9]+.*?'
		if (parmMatch){
			Res = parmMatcher[0][1].trim().toShort() 
		}	
		if(Res != 1080 && Res != 720 && Res != 480) Res = 480

		parmMatcher = resourceUrl =~ '^http://www\\.hd-trailers\\.net.*?pref=([a-z]+)'
		parmMatch = resourceUrl ==~ '^http://www\\.hd-trailers\\.net.*?pref=[a-z]+.*?'
		if (parmMatch){
			Pref = parmMatcher[0][1].trim()
		}
		
		if(rootUrl == "http://www.hd-trailers.net") {
			parmMatcher = resourceUrl =~ '^http://www\\.hd-trailers\\.net.*?start=([0-9]+)'
			parmMatch = resourceUrl ==~ '^http://www\\.hd-trailers\\.net.*?start=[0-9]+.*?'
			if (parmMatch){
				Start = parmMatcher[0][1].trim().toShort() - 1
				if(Start < 0 || Start > 2724) Start = 0
			}
			if(Start == 0) Page = 1
			else {
				Page = (Start/15)+1
				Plus = (Start%15)
			}
			//html = new URL(rootUrl + "/page/" + Page).getText()			
			//html = openURL(new URL(rootUrl + "/page/" + Page),
			//	"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.83 Safari/537.1")
			html = OpenProtURL(rootUrl + "/page/" + Page,"")

		}
		else {
			//html = new URL(rootUrl).getText()
			//html = openURL(new URL(rootUrl),
			//	"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.83 Safari/537.1")
			html = OpenProtURL(rootUrl,"")
		}

		def titleMatcher = html =~ '(?s)<title>(.*?)</title>'
		pageTitle = titleMatcher[0][1].trim()
		if(pageTitle.contains("Latest HD Trailers")) pageTitle = "Latest HD Trailers"
		else
		if(pageTitle.contains("Opening This Week")) pageTitle = "Opening This Week"
		else
		if(pageTitle.contains("Most Watched")) pageTitle = "Most Watched Trailers This Week"
		else
		if(pageTitle.contains("Box Office Top 10 Movies")) pageTitle = "Box Office Top 10 Movies"
		else
		if(pageTitle.contains("Coming Soon")) pageTitle = "Coming Soon"
		else
		if(pageTitle.contains("Netflix New Releases")) pageTitle = "Netflix New Releases"
		else {
			log("HDTrailer type not found or start value too high")
			return null
		}
		
		while (maxItems == -1 || itemsAdded < maxItems){
			
			if (html.count('<th class=') > 1 ){
				def sectionMatcher = html =~ '(?s)<th.class=(.*?)<th.class='
				html = sectionMatcher[0][1].trim()
			}
			
			if (html.count('<td class="indexTableTrailerImage">') > 0 ){

				
				def videoMatcher = html =~ '(?s)<td class="indexTableTrailerImage">(.*?)</td>'
				
				for( int i = Plus; i < videoMatcher.size() && (maxItems == -1 || itemsAdded < maxItems); i++ ) {
					def videoGetMatcher = videoMatcher[i][1] =~ '(?s).*?<a.href="(.*?)".*?title="(.*?)"'
					def videoMatch = videoMatcher[i][1] ==~ '(?s).*?<a.href=".*?".*?title=".*?".*?'
					if (!videoMatch) continue

					videoUrl = "http://www.hd-trailers.net" + videoGetMatcher[0][1].trim()

					videoTitle = videoGetMatcher[0][2].trim()
					videoTitle = videoTitle.replaceAll("#039;","'")
					videoTitle = videoTitle.replaceAll("&amp;","&")
					videoTitle = "[" + (((Page -1) * 15) + i + 1) + "]" + videoTitle
					
					WebResourceItem item = new WebResourceItem(title: videoTitle, additionalInfo: ['videoUrl':videoUrl,'itemNum': ((Page-1) * 15) + i + 1, 'Res': Res, 'Pref': Pref])
					
					items << item
					itemsAdded++
				}
			}	
			
			if(rootUrl == "http://www.hd-trailers.net" && itemsAdded < maxItems) {  
				Page = Page + 1
				Plus = 0
				html = openUrl(new URL("http://www.hd-trailers.net/page/" + Page),
					"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.83 Safari/537.1")
				
				titleMatcher = html =~ '(?s)<title>(.*?)</title>'
				pageTitle = titleMatcher[0][1].trim()
				if(pageTitle.contains("Latest HD Trailers")) pageTitle = "Latest HD Trailers"
			}
			else
				break
		}
	 	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 itemNum = item.getAdditionalInfo()['itemNum'] + 1
		Short Res = item.getAdditionalInfo()['Res']
		String Pref = item.getAdditionalInfo()['Pref']
		
		String linkUrl = ""
		String thumbnailUrl = ""
		String UserAgent = ""
		
		log("Source Link: " + videoUrl)


		def videohtml = OpenProtURL(videoUrl,"")

		def thumbMatcher = videohtml =~ '(?s)<meta name="thumbnail".*?content=.*?href="(.*?)".*?'
		thumbnailUrl = thumbMatcher[0][1].trim()
		
		def videoMatcher = videohtml =~ '(?s)<tr.style=.*?itemprop="trailer".*?itemprop="name">(.*?)<.*?bottomTableResolution.*?href="(.*?)".*?</td>(.*?)TableIcon">.*?'
		
		linkUrl = videoMatcher[0][2].trim()
		def trailerFound = false
		int i
		
		for( i = 0; i < videoMatcher.size(); i++ ) {
		
			if ((!videoMatcher[i][1].trim().contains("Trailer") && !videoMatcher[i][1].trim().contains("Teaser")) || videoMatcher[i][1].trim().contains("Red Band Trailer")) {
				continue
			}
			
			trailerFound = true
			linkUrl = videoMatcher[i][2].trim() 
			
			if (Pref == "apple" && !linkUrl.contains("trailers.apple.com")) {
			
				for( int j = i+1; j < videoMatcher.size(); j++ ) {
					linkUrl = videoMatcher[j][2].trim()
					if (linkUrl.contains("trailers.apple.com") && (videoMatcher[j][1].trim().contains("Trailer") || videoMatcher[j][1].trim().contains("Teaser"))) {
						i = j
						break
					}
				}
			}
			break
		}
	
		if(trailerFound == false) i=0
		
		def videoMatcher2
		if (Res == 720 && videoMatcher[i][3].contains("720")){
			videoMatcher2 = videoMatcher[i][3] =~ '(?s)href="(.*?)".*?'
			linkUrl = videoMatcher2[0][1].trim() 
		}
			
		if (Res == 1080 && videoMatcher[i][3].contains("1080")) {
			videoMatcher2 = videoMatcher[i][3] =~ '(?s)href=.*?href="(.*?)".*?'
			linkUrl = videoMatcher2[0][1].trim() 
		}
		else if(Res==1080 && videoMatcher[i][3].contains("720")){
			videoMatcher2 = videoMatcher[i][3] =~ '(?s)href="(.*?)".*?'
			linkUrl = videoMatcher2[0][1].trim()
			Res = 720
		}

		def saveUrl = linkUrl

		UserAgent = ""

		if (linkUrl.contains("trailers.apple.com")) {
			UserAgent = "QuickTime"
		}
		else if (linkUrl.contains("www.youtube.com")) {
			String Formats  = "37, 22, 35, 18, 34, 6, 5"
			String fmt
			String itag
			def fmtMatcher = linkUrl =~ '.*?fmt=([0-9]+)'
			def fmtMatch = linkUrl ==~ '.*?fmt=[0-9]+'
			if (fmtMatch) fmt = fmtMatcher[0][1].trim()
			else fmt = "35"
			if (fmt == "22") Formats  = "22, 35, 18, 34, 6, 5"
			if (fmt == "35") Formats  = "35, 18, 34, 6, 5"
			if (fmt == "18") Formats  = "18, 34, 6, 5"
			if (fmt == "34") Formats  = "34, 6, 5"

			videohtml = openURL(new URL(linkUrl),
				"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.83 Safari/537.1")


			def flashMatch = videohtml ==~ '(?s).*?url_encoded_fmt_stream_map=.*?'
			if (!flashMatch){
				log("NO ENTRIES FOR THIS ITEM - \'$videoTitle\'") 
				return null
			}

			def videoMatch = videohtml =~ '(?s)stream_map=(.*?);.*?'
		
			videoMatcher = videoMatch[0][1] =~ '(?s)(.*?)itag%253D(.*?)%(.*?)%2C'
			int j
			for( j = 0; j < videoMatcher.size(); j++ ) {
				itag = videoMatcher[j][2].trim()
				if (Formats.contains(itag)) {
					linkUrl = videoMatcher[j][1] + "itag%253D" + videoMatcher[j][2] + "%" + videoMatcher[j][3] + "%2C"

					videoMatcher = linkUrl =~ '(.*?)url%3D(.*?)%2C'
					linkUrl = videoMatcher[0][2] + "%26" + videoMatcher[0][1] + "%2C"
					
					videoMatcher = linkUrl =~ '(.*?)type%3D.*?%26(.*?)%2C'
					linkUrl = videoMatcher[0][1] + videoMatcher[0][2] + "%2C"

					videoMatcher = linkUrl =~ '(.*?)fallback_host%3D.*?%26(.*?)%2C'
					linkUrl = videoMatcher[0][1] + videoMatcher[0][2] + "%2C"

					videoMatcher = linkUrl =~ '(.*?)itag%3D.*?%26(.*?)%2C'
					linkUrl = videoMatcher[0][1] + videoMatcher[0][2] + "%2C"
					
					linkUrl = linkUrl.replaceFirst("sig","signature")
					
					linkUrl = linkUrl.replaceFirst("%26%2C","")
					
					videoMatcher = linkUrl =~ 'expire%253D(.*?)%'
					def expiryDate = new Date(videoMatcher[0][1].trim().toLong()*1000)

					linkUrl = URLDecoder.decode(linkUrl)
					linkUrl = URLDecoder.decode(linkUrl)
					linkUrl = URLDecoder.decode(linkUrl)
					
					break 
				}
			}
		}
		else if (linkUrl.contains("yahoo-redir.php")) {
		
			linkUrl = linkUrl.replaceAll("&amp;","&")
			videohtml = openURL(new URL(linkUrl),
				"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.83 Safari/537.1")


			def linkMatcher = videohtml =~ /(?s)text.javascript.*?text.javascript.*?src="(.*?)".*?trailer\(.*?'(.*?)'.*?/
			linkUrl = linkMatcher[0][1]
			def media_id = linkMatcher[0][2]
			videohtml = openURL(new URL(linkUrl),
				"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.83 Safari/537.1")

			linkMatcher = videohtml =~ /(?s)params.*?'q'.*?:.*?"(.*?)",.*?getJSON\(.*?'(.*?)'.*?/
			def params = linkMatcher[0][1]
			def header = linkMatcher[0][2]
			params = params.replaceFirst(/'"\+media_id\+"'/,"'"+media_id+"'")
			params=params.replaceAll("\\s+","+")
			params=params.replaceAll("=","%3D")
			header=header.replaceFirst("\\?callback=\\?","")
			

			linkUrl = header + "?q=" + params + "&env=prod&format=json"
			//videohtml = new URL(linkUrl).getText()
			videohtml = openURL(new URL(linkUrl),
				"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.83 Safari/537.1")
			
			def mimes = videohtml =~ '(?s)"mime_type":(.*?)}.*?'
			def mimesMatcher
			for( int k = 0; k < mimes.size() ; k++ ) {
				mimesMatcher = mimes[k][1] =~ '(?s)"path":"(.*?)&d=.*?\\+atlas(.*?)".*?"host":"(.*?)".*?height":(.*?)\\.0'
				if (mimesMatcher[0][4].toShort() == Res) break
			}
			
			header = mimesMatcher[0][3]
			def header2 = mimesMatcher[0][1]
			params = mimesMatcher[0][2]
			linkUrl = header + header2 + "&d=+y+" + media_id + "++atlas" + params 
		}

		if(linkUrl == "") return null
		
		log("Extracted url: " + saveUrl )

		linkUrl = linkUrl.replaceAll("&amp;","&")
		
		//linkUrl = linkUrl.replaceAll(",","%2C")

		def cacheKey = videoUrl  + "_" +  Res 

		//return new ContentURLContainer(fileType: MediaFileType.VIDEO, contentUrl: linkUrl, thumbnailUrl: thumbnailUrl, userAgent: UserAgent, cacheKey: cacheKey, expiresImmediately: true)
		return new ContentURLContainer(fileType: MediaFileType.VIDEO, contentUrl: linkUrl, thumbnailUrl: thumbnailUrl, userAgent: UserAgent, cacheKey: cacheKey, expiresImmediately: true)
	}
	
	static void main(args) {
		HDTrailers extractor = new HDTrailers()
				
		assert extractor.extractorMatches( new URL("http://www.hd-trailers.net") )
		assert !extractor.extractorMatches( new URL("http://google.com/feeds/api/standardfeeds/top_rated?time=today") )
		WebResourceContainer container = extractor.extractItems( new URL("http://www.hd-trailers.net?start=1"), 10)    
		//WebResourceContainer container = extractor.extractItems( new URL("http://www.hd-trailers.net/coming-soon?res=1080"), 12)    
		//WebResourceContainer container = extractor.extractItems( new URL("http://www.hd-trailers.net/top-movies"),6)
		//WebResourceContainer container = extractor.extractItems( new URL("http://www.hd-trailers.net/most-watched?res=1080"), -1)    
		println container

		container.getItems().each {																					
            ContentURLContainer result = extractor.extractUrl(it, PreferredQuality.MEDIUM)							
            println result 	
		}							 
	}
}
