import org.serviio.library.metadata.*
import org.serviio.library.online.*
import org.serviio.util.*

/**
 * WebResource extractor plugin for ilive.to.
 * 
 * @author jhb50
 *
 * Version 1 - May 3, 2012
 * Version 2 - Aug. 5, 2012 - Speed up extraction to fix Serviio V1 errors.
 * Version 3 - Aug. 13, 2012 - Add version logging
 * Version 4 - Aug. 24, 2012 - Add Page read log, correct for new ilive code
 * Version 5 - Oct. 16, 2012 - New IP Address
 * Version 6 - Oct. 21, 2012 - New IP Address, Display all items regardless of Console limit.
 * Version 7 - Nov. 10, 2012 - Add category support
 * Version 8 - Jan.  6, 2013 - New IP Address, expires immediately, sort option, added ETimers
 * Version 9 - Feb.  3, 2013 - New web format, genurls added by default to minimize extracts
 * Version 10 - Feb. 5, 2013 - Support Quick Refresh for subsets.
 * Version 11 - Feb.10, 2013 - Update refresh logic
 * Version 12 - Mar.11, 2013 - New IP Address
 * Version 13 - Apr.17, 2013 - New web format
 * Version 14 - Apr.30, 2013 - Fix web format code
 * Version 15 - May 14, 2013 - New Page Icon, Detect Site Unavailable, Default Title Sort, add Terms
 * Version 16 - May 28, 2013 - Minor bug fix
 *
 *
 */
class ILive extends WebResourceUrlExtractor {

	long StartETime = 0
	long LastETime2 = 0
	long LastETime3 = 0
	def debug = 0
	
	List<WebResourceItem> newitems = []
	List<WebResourceItem> olditems = []

	
	final VALID_FEED_URL = '^(?:https?://)?(?:www\\.)?ilive\\.to/channels.*?'
	
	String getExtractorName() {
		return 'ILive'
	}

	boolean extractorMatches(URL feedUrl) {

		return feedUrl ==~ VALID_FEED_URL
	}

	int getVersion() {
		return 16
	}

	Long ETimer(String msg){
		long CurrentTime = System.currentTimeMillis()
		long Elapsed = CurrentTime - StartETime
		if (msg != null){
			log("$msg = $Elapsed msec")
		}
		return Elapsed
	}

	Long ETimer2(String msg){
		long CurrentTime = System.currentTimeMillis()
		long Elapsed = CurrentTime - LastETime2
		LastETime2 = CurrentTime
		if (msg != null){
			log("$msg = $Elapsed msec")
		}
		return Elapsed
	}
	
	Long ETimer3(String msg){
		long CurrentTime = System.currentTimeMillis()
		long Elapsed = CurrentTime - LastETime3
		LastETime3 = CurrentTime
		if (msg != null){
			log("$msg = $Elapsed msec")
		}
		return Elapsed
	}
		
	Boolean URLExists(String srcURL){
		URL fileURL = new URL(srcURL);
		if(((HttpURLConnection) fileURL.openConnection()).getResponseCode() == 404){
			return false
		}
		return true
	}
	
	WebResourceContainer extractItems(URL resourceUrl, int maxItems) {

		log("Parsing with ILive V${getVersion()}")
		
		StartETime = System.currentTimeMillis()
		ETimer2()										

		def genurls = 1
		def curDate = new Date(System.currentTimeMillis()+300000)
		olditems = []
		if (newitems){
			def newitemssize = newitems.size()
			def nli = newitems.iterator()
			while (nli.hasNext()){
				def newEntry = nli.next()
				if(newEntry.getAdditionalInfo()['XexpiresImmediately']!= true) continue
				def SavedExpiryDate = newEntry.getAdditionalInfo()['XexpiresOn']
				if(SavedExpiryDate > new Date(0) && curDate >= SavedExpiryDate){
					if (debug) log("Expired On =-" + SavedExpiryDate + "- so deleted. " + newEntry)
					continue
				}
				olditems << newEntry
			}
			def olditemssize = olditems.size()
			log ( olditemssize + " items saved, " + (newitemssize - olditemssize) +  " expired" )
			olditems = olditems.drop(olditemssize-300)
			newitems = olditems
		}
		
		
		while(1) {
			def test_text = openURL(new URL("http://www.dogpile.com"),
				"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.83 Safari/537.1")
			def testMatch = test_text ==~ '(?s).*?Dogpile Web Search.*?'
			if (testMatch) break
		}
		
		List<WebResourceItem> items = []
		def itemsAdded = 0;
		def pageitemsAdded = 0;
		String thumbUrl
		String linkUrl
		String videoTitle
		String fileNum
		String SortSw = "0"
		def pages = 99

		long Refreshi = 0
		long Refresha = 0

		
		
		def parmMatcher = resourceUrl =~ '^http://www\\.ilive\\.to/channels.*?genurls=([0-1])'
		def parmMatch = resourceUrl ==~ '^http://www\\.ilive\\.to/channels.*?genurls=[0-1].*?'
		if (parmMatch){
		    genurls = parmMatcher[0][1].trim()  
		}

		parmMatcher = resourceUrl =~ '^http://www\\.ilive\\.to/channels.*?debug=([0-1])'
		parmMatch = resourceUrl ==~ '^http://www\\.ilive\\.to/channels.*?debug=[0-1].*?'
		if (parmMatch){
		    debug = parmMatcher[0][1].trim()  
		}

		parmMatcher = resourceUrl =~ '^http://www\\.ilive\\.to/channels.*?refresh=([0-9]+)'
		parmMatch = resourceUrl ==~ '^http://www\\.ilive\\.to/channels.*?refresh=[0-9]+.*?'
		if (parmMatch){
			Refreshi = parmMatcher[0][1].trim().toLong()
			long curTime=System.currentTimeMillis()/60000
			Refresha = (System.currentTimeMillis()/60000) + Refreshi + 5
		}

		parmMatcher = resourceUrl =~ '^http://www\\.ilive\\.to/channels.*?sort=([0-2])'
		parmMatch = resourceUrl ==~ '^http://www\\.ilive\\.to/channels.*?sort=[0-2].*?'
		if (parmMatch){
			SortSw = parmMatcher[0][1].trim()
		}
		
		parmMatcher = resourceUrl =~ '^http://www\\.ilive\\.to/channels.*?pages=([0-9]+)'
		parmMatch = resourceUrl ==~ '^http://www\\.ilive\\.to/channels.*?pages=[0-9]+.*?'
		if (parmMatch){
			pages = parmMatcher[0][1].trim().toInteger()
		}

		def termsMatcher
		def terms = ""
		parmMatcher = resourceUrl =~ "^http://www\\.ilive\\.to/channels.*?terms=([A-Za-z0-9,\\s]+)"
		parmMatch = resourceUrl ==~ "^http://www\\.ilive\\.to/channels.*?terms=[A-Za-z0-9,\\s]+.*?"
		if (parmMatch){
			termsMatcher = parmMatcher[0][1] + ","
		}
		terms = termsMatcher =~ "(.*?),.*?"	
			println terms.count

		String maskUrl = resourceUrl.toString()

		if (resourceUrl.toString().contains("?")){
			def maskMatcher = resourceUrl =~ '^(.*?)\\?.*?'
			maskUrl = maskMatcher[0][1].trim()
		}

		String pageUrl = maskUrl + "?sort=" + SortSw
		println "read " + pageUrl
		String html  = openURL( new URL(pageUrl),
			"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.83 Safari/537.1") 

		def pageMatcher
		while(1){
			pageMatcher = html =~ '(?s)<br class="clear".*?<ul.*?class="clist clearfix">(.*?)</ul>'
			if(pageMatcher) break
			else{
				println "use 2"
				pageMatcher = html =~ '(?s)<div class="clear">.*?<div class="leftcol">(.*?)<div class="rightcol">'
			}
			if(pageMatcher) break
			else {
				println "use 3"
				pageMatcher = html =~ '(?s)<table.*?id="channellist".*?>(.*?)</table>'
			}
			if(pageMatcher) break
			else {
				println "use 4"
				pageMatcher = html =~ '(?s)<br class="clear"(.*?)<div class="rightcol">'
			}
			if(pageMatcher) break
			else{
				log("Unable to access Ilive. It may be blocked by Captcha.")
				println "Unable to access Ilive. It may be blocked by Captcha."
				return
			}
		}
		String page = pageMatcher[0][1]
		if (page.size() < 80){
		    println "No items - returning"
			return null
		}

		def titleMatcher = html =~ '(?s)<h1 style=".+?">(.*?)</h1>'
		String pageTitle = titleMatcher[0][1].trim()
		pageTitle = pageTitle.replaceAll("\\s+"," ")
		def pageTitle2 = pageTitle.replaceAll("\\|", " ")
		String pageThumb = "https://sites.google.com/site/serviiorss/ilive.png"
				
		for( int j = 1; j < pages+1; j++) {
			def sectMatcher 
			while (1) {
				sectMatcher = page =~ '(?s)<li(.*?)<span class="viewers">'
				if(sectMatcher) break
				else {
					if (j==1) println "use section 2"
					sectMatcher = page =~ '(?s)<div class="channel-listing-container(.*?)<span class="viewers">'
				}
				if(sectMatcher) break
				else {
					if (j==1) println "use section 3"
					sectMatcher = page =~ '(?s)<div class="cl-cont(.*?)<span class="viewers">'
				}
				if(sectMatcher) break
				else {
					println "Section Format Changed - Unable to Parse ILive"
					log("Section Format Changed - Unable to Parse ILive")
					return
				}
			}

			for( int i = 0; i < sectMatcher.size(); i++ ) {
			
				if (ETimer() > 27000){
					break
				}
				

				if(sectMatcher[i][1].contains('<span class="premium_only">Premium Only<')) continue
				def videoMatcher = sectMatcher[i][1] =~ '(?s)view/(.*?)/.*?src="(.*?)".*?<a.href="(.*?)".*?<strong>(.*?)<'
				videoTitle = videoMatcher[0][4].trim()
				videoTitle = videoTitle.replaceAll("\\s+"," ") 
				
				if (videoTitle == "Forums Channel") continue
				
				def termsMatched = 0
				println terms.count
				if (terms.count > 0){
					for (tnum in 0..<terms.count){
						if (videoTitle.contains(terms[tnum][1])){ 
							termsMatched = 1
							break
						}
					}
					if (termsMatched == 0) continue
				}
				
				fileNum = videoMatcher[0][1].trim()

				videoTitle = videoTitle + "-" + fileNum
				
				linkUrl = videoMatcher[0][3].trim()
				
				thumbUrl = videoMatcher[0][2].trim()
				
				def playpath = thumbUrl =~ 'snapshots/(.*?)_'

				def itemkey = "ILive_" + linkUrl + "_" + playpath[0][1]
				
				WebResourceItem item = new WebResourceItem(title: videoTitle, additionalInfo: ['itemkey':itemkey,'resourceUrl':resourceUrl,'linkUrl':linkUrl,'fileNum':fileNum,'thumbUrl':thumbUrl,'refresha':Refresha])

				item.additionalInfo.put('gen',"false")
				if(olditems && itemkey){
					for (int oij=olditems.size(); oij > 0; oij--){
						String olditem = olditems.getAt(oij-1).toString()
						if(olditem.contains(itemkey)){
							item.additionalInfo.put('oindx',oij-1)
							if (genurls) item.additionalInfo.put('gen',"true")
							break
						}
					}
				}
                                                                                                                                                                                                                                                                        
				items << item
				pageitemsAdded++			
				itemsAdded++			
			}
			
			ETimer2 ("Page " + j + " - " + pageitemsAdded + " Items Found")
			
			pageitemsAdded = 0
			
			if (ETimer() > 25000){
				log ("Time Limit of 30 Seconds Reached") 
				break
			}
				
			String npageUrl = maskUrl + "?p=" + (j+1) + "&sort=" + SortSw
			if (j < pages && URLExists(npageUrl)){
				println "read page " + (j+1) + " " + npageUrl
				html  = openURL( new URL(npageUrl),
					"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.83 Safari/537.1") 
				
				pageMatcher = html =~ '(?s)<br class="clear"(.*?)<div class="rightcol">'
				String npage = pageMatcher[0][1]

				if (npage == page) {
					println "duplicate page"
					break
				}
				else page = npage

				if (page.size() < 80){
					println ""
					ETimer2 ("Page " + (j+1) + " - No Items Found")
					break
				}
			}
			else {
				println "Page does not exist"
				break
			}
		}

		
		if (SortSw == "0") items = items.sort{it.title}
		
		
		def Refreshat
		if (Refreshi == 0){
			log ("Folder Refresh Set to Console Default")
			Refreshat = "Console Default time"
		}
		else{
			Refreshat = new Date((Refresha-5)*60000).format("H:mm 'on' E M/dd/yyyy ").trim()
			log ("Folder Refresh Set to " + Refreshat )
		}

		if (itemsAdded == 0 || Refreshi != 0){
			linkUrl = "http://lastitem"
			if (itemsAdded == 0) thumbUrl = "https://sites.google.com/site/serviiorss/noevents.jpg"
			else thumbUrl = "https://sites.google.com/site/serviiorss/nomoreitems.jpg"
			videoTitle = "Next Refresh at $Refreshat"
			if (itemsAdded == 0) log ("ADDED 'NO EVENTS' - $videoTitle")
			else log ("ADDED 'NO MORE ITEMS' - $videoTitle")
			WebResourceItem item = new WebResourceItem(title: videoTitle, 
				additionalInfo: ['resourceUrl':resourceUrl,'linkUrl':linkUrl,'thumbUrl':thumbUrl,'refresha':Refresha])

			item.additionalInfo.put('gen',"false")
			items << item
		}

		ETimer("Total $itemsAdded Items Found")
		return new WebResourceContainer(title: pageTitle, thumbnailUrl: pageThumb, items: items)
	}
	
	ContentURLContainer extractUrl(WebResourceItem item, PreferredQuality requestedQuality) {		
		String videoTitle = item.title
		String linkUrl = item.getAdditionalInfo()['linkUrl']
		String thumbnailUrl = item.getAdditionalInfo()['thumbUrl']
		String resourceUrl = item.getAdditionalInfo()['resourceUrl']
		String fileNum = item.getAdditionalInfo()['fileNum']
		long Refresha = item.getAdditionalInfo()['refresha']
		

		String rtmpUrl = ""
		String linkHtml 
		String secCode = ""
		Date expiryDate
		def expiresImmediately
		def cacheKey		
		
		String gen = item.getAdditionalInfo()['gen']
		if(gen == "false"){
			println "\r\nExtracting URL for $videoTitle"
		
			if (linkUrl.contains("http://lastitem")){
				if (Refresha > 0) expiryDate = new Date(Refresha * 60000)
				rtmpUrl = "rtsp://a1709.l1856953708.c18569.g.lm.akamaistream.net:554/D/1709/18569/v00/reflector:53708"
				secCode = "abcdefghi"
				cacheKey = "http://lastitem_" + secCode
				expiresImmediately = false
			}
			else{
			
				
				println "LinkUrl = $linkUrl"

				linkHtml = 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 secMatch = linkHtml ==~ '(?s).*?flashplayer: ".*?streamer: ".*?file: ".*?'
				def secMatcher = linkHtml =~ '(?s)flashplayer: "(.*?)".*?streamer: "(.*?)".*?file: "(.*?).flv.*?'
				if (secMatch){
					secCode = secMatcher[0][3].trim()
				}
				else{
					log ("No playpath found for $linkUrl")
					println "No playpath found for $linkUrl"
					return
				}
				
				rtmpUrl = secMatcher[0][2].trim() + " playpath=" + secCode + " swfurl=" + secMatcher[0][1].trim() + " pageurl=http://www.ilive.to live=1" 

				println "rtmpUrl = $rtmpUrl"
					
				def videoTitle2 = videoTitle.replaceAll("\\|", " ")
				
				
				log("Extracted Url for $linkUrl - $secCode")
			
				cacheKey = "ILive_" + videoTitle + "_" + secCode
				
				expiresImmediately = true

			}
			
			item.additionalInfo.put('XcontentUrl',rtmpUrl)
			item.additionalInfo.put('XthumbnailUrl',thumbnailUrl)
			item.additionalInfo.put('XexpiresOn',expiryDate)
			item.additionalInfo.put('XexpiresImmediately',expiresImmediately)
			item.additionalInfo.put('XcacheKey',cacheKey)
			def oindx = item.getAdditionalInfo()['oindx']
			if(oindx){
				if (debug) log("item before = " + newitems[oindx])
				newitems[oindx] = item
				if (debug) log("item after = " + newitems[oindx])
			}
			else {
				oindx = newitems.size()
				item.additionalInfo.put('oindx',oindx)
				if (debug) log("item added = " + item)
				newitems << item
			}
		
		}//END of non gen EXTRACT
		
		else{   //START OF gen GENERATE
			println "\r\nGenerating Url for $videoTitle"
			log("Generated Url for $linkUrl")
			item.additionalInfo.put('gen',"false")
			def oindx = item.getAdditionalInfo()['oindx']
			rtmpUrl = olditems.getAt(oindx).getAdditionalInfo()['XcontentUrl']
			thumbnailUrl = olditems.getAt(oindx).getAdditionalInfo()['XthumbnailUrl']
			expiryDate = olditems.getAt(oindx).getAdditionalInfo()['XexpiresOn']
			expiresImmediately = olditems.getAt(oindx).getAdditionalInfo()['XexpiresImmediately']
			cacheKey = olditems.getAt(oindx).getAdditionalInfo()['XcacheKey']
		}

		return new ContentURLContainer(fileType: MediaFileType.VIDEO, contentUrl: rtmpUrl, thumbnailUrl: thumbnailUrl, 
			cacheKey: cacheKey, expiresOn: expiryDate, expiresImmediately: expiresImmediately, live: true)
	}
}																												
