import org.serviio.library.metadata.*
import org.serviio.library.online.*
import org.apache.log4j.*

/**
 * WebResource extractor plugin for player.canalplus.fr
 *
 * @author Illico
 * @version 1.1
 *
 */
class CanalPlus extends WebResourceUrlExtractor {

	final VALID_FEED_URL = '(^http://player.canalplus.fr/#/\\d*{6}$)||(^http://player.canalplus.fr/#/.*/.*$)'
	final BASE_URL = "http://webservice.canal-plus.com/rest/bigplayer/"
	
	static Logger LOGGER = Logger.getLogger(CanalPlus.class);
	
	String getExtractorName() {
		return getClass().getName()
	}
	
	boolean extractorMatches(URL feedUrl) {
		return feedUrl ==~ VALID_FEED_URL
	}
	
	WebResourceContainer extractItems(URL resourceUrl, int maxItems) {
		String WebResourceTitle = "CANAL PLUS PLAYER"
		String WebResourceThumbnailUrl = "http://www.news-hightech.com/wp-content/uploads/2011/10/canalplus.jpg"
		LOGGER.info("1: url " + resourceUrl.toString())
		// Extract Url informations
		def ThemeMatcher = resourceUrl.toString() =~ '^http://player.canalplus.fr/#/(.*?)/(.*?)$'
			assert ThemeMatcher.getCount() > 0, "Error : Url format http://player.canalplus.fr/#/(Thematique)/(Selection)"
			String ThemeSelected     = ThemeMatcher[0][1].toUpperCase();                     println "ThemeSelected     : "+ThemeSelected
			String SelectionSelected = ThemeMatcher[0][2].replaceAll("-"," ").toUpperCase(); println "SelectionSelected : "+SelectionSelected
		
		//LOGGER.info("2: ThemeMatcher " + ThemeMatcher)
			
		// GET INIT PLAYER and Extract Subtheme ID
		def PlayerXml = new XmlParser().parse(BASE_URL + "initPlayer/")
			assert PlayerXml.name() == "INIT_PLAYER", "Error : Could not parse Init Page"
		
		def Thematiques = PlayerXml.THEMATIQUES.THEMATIQUE
		
		def Selection = []
		for( int i = 0; i < Thematiques.size(); i++ ) {
			//LOGGER.info("Thematiques[i] :  " + Thematiques[i])
			
			def Selections = Thematiques[i].SELECTIONS.SELECTION
			
			for( int j = 0; j < Selections.size(); j++ ) {
				//LOGGER.info("Selections[j] :  " + Selections[j])
				def text = Selections[j].NOM.text().replaceAll("é","e").replaceAll("è","e").replaceAll("à","a").toUpperCase()
				
				//LOGGER.info("text :  " + text)
				//LOGGER.info("text == SelectionSelected :  " + text == SelectionSelected)
				if (text == SelectionSelected) {
					Selection.addAll(Selections[j])
				}
			}
		}
			
		//LOGGER.info("5: Selection " + Selection)
	
		List<WebResourceItem> items = []
		if (Selection[0] == null) {
			LOGGER.error("-> " + resourceUrl.toString() + " : Selection[0] == null : " + Selection)
			def MozaicXml = new XmlParser().parse("http://service.canal-plus.com/video/rest/search/cplus/"+SelectionSelected)
			
			LOGGER.info("5: MozaicXml " + MozaicXml)
			LOGGER.info("5a: MozaicXml.VIDEO.size() " + MozaicXml.VIDEO.size())
			
			def ItemsAdded = 0;
			for( int i = 0; i < MozaicXml.VIDEO.size() && (maxItems == -1 || ItemsAdded < maxItems) ; i++ ) {
			
				LOGGER.info("5b: MozaicXml.VIDEO[i] " + MozaicXml.VIDEO[i])
				
				String WebResourceItemTitle        = MozaicXml.VIDEO[i].INFOS.TITRAGE.TITRE.text()+" - "+MozaicXml.VIDEO[i].INFOS.TITRAGE.SOUS_TITRE.text()
				String WebResourceItemThumbnailUrl = MozaicXml.VIDEO[i].MEDIA.IMAGES.GRAND.text()
				String WebResourceItemUrl_LOW      = MozaicXml.VIDEO[i].MEDIA.VIDEOS.BAS_DEBIT.text()
				String WebResourceItemUrl_MEDIUM   = MozaicXml.VIDEO[i].MEDIA.VIDEOS.HAUT_DEBIT.text()
				String WebResourceItemUrl_HIGH     = MozaicXml.VIDEO[i].MEDIA.VIDEOS.HD.text()
				String WebResourceItemInfoUrl      = MozaicXml.VIDEO[i].URL.text()
				WebResourceItem item = new WebResourceItem(title: WebResourceItemTitle,
												additionalInfo: [	'WebResourceItemThumbnailUrl': WebResourceItemThumbnailUrl,
																	'WebResourceItemUrl_LOW'     : WebResourceItemUrl_LOW,
																	'WebResourceItemUrl_MEDIUM'  : WebResourceItemUrl_MEDIUM,
																	'WebResourceItemUrl_HIGH'    : WebResourceItemUrl_HIGH,
																	'WebResourceItemInfoUrl'     : WebResourceItemInfoUrl])
				items << item
				ItemsAdded++			
			}
			
		} else {
			String IDSelected = Selection[0].ID.text()
			// GET MOZAIC PAGE
			def MozaicXml = new XmlParser().parse(BASE_URL + "getMEAs/"+IDSelected)
				assert MozaicXml.name() == "MEAS", "Error : Could not parse Mozaic Page"
			// Extract Mozaic Video resources
			def ItemsAdded = 0;
			for( int i = 0; i < MozaicXml.MEA.size() && (maxItems == -1 || ItemsAdded < maxItems) ; i++ ) {
				String WebResourceItemTitle        = MozaicXml.MEA[i].INFOS.TITRAGE.TITRE.text()+" - "+MozaicXml.MEA[i].INFOS.TITRAGE.SOUS_TITRE.text()
				String WebResourceItemThumbnailUrl = MozaicXml.MEA[i].MEDIA.IMAGES.GRAND.text()
				String WebResourceItemId           = MozaicXml.MEA[i].ID.text()
				// Extract Videos Url
				def VideosXml = new XmlParser().parse(BASE_URL + "getVideosLiees/"+ WebResourceItemId)
					assert VideosXml.name() == "VIDEOS"
				def VideoSelected = VideosXml.VIDEO.findAll{ it.ID.text() == WebResourceItemId }
					assert VideoSelected != null, "La Video "+WebResourceItemId+" choisi n'existe pas dans le catalogue"
				String WebResourceItemUrl_LOW      = VideoSelected[0].MEDIA.VIDEOS.BAS_DEBIT.text()
				String WebResourceItemUrl_MEDIUM   = VideoSelected[0].MEDIA.VIDEOS.HAUT_DEBIT.text()
				String WebResourceItemUrl_HIGH     = VideoSelected[0].MEDIA.VIDEOS.HD.text()
				String WebResourceItemInfoUrl      = VideoSelected[0].URL.text()
				WebResourceItem item = new WebResourceItem(title: WebResourceItemTitle,
												additionalInfo: [	'WebResourceItemThumbnailUrl': WebResourceItemThumbnailUrl,
																	'WebResourceItemUrl_LOW'     : WebResourceItemUrl_LOW,
																	'WebResourceItemUrl_MEDIUM'  : WebResourceItemUrl_MEDIUM,
																	'WebResourceItemUrl_HIGH'    : WebResourceItemUrl_HIGH,
																	'WebResourceItemInfoUrl'     : WebResourceItemInfoUrl])
				items << item
				ItemsAdded++			
			}
		}
		
		LOGGER.info("6: items " + items)
		
		return new WebResourceContainer(title: WebResourceTitle, thumbnailUrl: WebResourceThumbnailUrl, items: items)
	}

	ContentURLContainer extractUrl(WebResourceItem item, PreferredQuality requestedQuality) {
		String ItemVideoUrl
		switch (requestedQuality) {
			case "LOW"    : ItemVideoUrl = item.getAdditionalInfo()['WebResourceItemUrl_LOW'];break;
			case "MEDIUM" : ItemVideoUrl = item.getAdditionalInfo()['WebResourceItemUrl_MEDIUM'];break;
			case "HIGH"   : ItemVideoUrl = item.getAdditionalInfo()['WebResourceItemUrl_HIGH'];break;
			default: ItemVideoUrl = item.getAdditionalInfo()['WebResourceItemUrl_HIGH'];break;
			}
		String contentUrl
		if (ItemVideoUrl.startsWith('http:')) {
			contentUrl = ItemVideoUrl
			println " contentUrl(http): "+contentUrl
		} else {
			def VideoUrlMatcher = ItemVideoUrl =~ '(rtmp.*://.*?)/(.*?/.*?)/(.*)'
				assert VideoUrlMatcher.getCount() > 0, "Le lien de la video n'est pas supporté "+ItemVideoUrl
			if ( VideoUrlMatcher[0][3].endsWith('.mp4') ) {
				contentUrl = VideoUrlMatcher[0][1]+":80/"+VideoUrlMatcher[0][2]+" app="+VideoUrlMatcher[0][2]+" playpath=mp4:"+VideoUrlMatcher[0][3]+" swfVfy=1"
				println " contentUrl(mp4): "+contentUrl
			}else{
				contentUrl = VideoUrlMatcher[0][1]+":80/"+VideoUrlMatcher[0][2]+" app="+VideoUrlMatcher[0][2]+" playpath="+VideoUrlMatcher[0][3]+" swfVfy=1"
				println " contentUrl(flv): "+contentUrl
			}
		}
		return new ContentURLContainer(fileType: MediaFileType.VIDEO, contentUrl: contentUrl, thumbnailUrl: item.getAdditionalInfo()['WebResourceItemThumbnailUrl'])
	}

/*********************************************
 * MAIN
 *********************************************/
	static void main(args) {
		def TestUrl = new URL("http://player.canalplus.fr/#/emissions/le-grand-journal")
		// http://player.canalplus.fr/#/sport/tout-le-football -> OK
		// http://player.canalplus.fr/#/cinema/les-dernieres-ba -> OK but up to 200 videos !!!
		// http://player.canalplus.fr/#/emissions/le-grand-journal -> OK
		// http://player.canalplus.fr/#/divertissement/les-guignols -> OK
		CanalPlus extractor = new CanalPlus()
			println "PluginName : " + extractor.getExtractorName();
			println "TestMatch  : " + extractor.extractorMatches(TestUrl);
		WebResourceContainer container = extractor.extractItems(TestUrl, 20);
			println "**** HIGH ****"  ;extractor.extractUrl(container.getItems()[0], PreferredQuality.HIGH)
			println "**** MEDIUM ****";extractor.extractUrl(container.getItems()[0], PreferredQuality.MEDIUM)
			println "**** LOW ****"   ;extractor.extractUrl(container.getItems()[0], PreferredQuality.LOW)
	}
}