import java.awt.PageAttributes.MediaType;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.text.*;

import org.restlet.*
import groovy.json.*

import org.restlet.resource.ClientResource

import org.restlet.data.*
import org.restlet.representation.*
import org.serviio.library.metadata.*
import org.serviio.library.online.*
import org.serviio.util.*



/**
 * WebResource extractor plugin for http://www.ceskatelevize.cz/ivysilani
 *
 * @author mv
 * @version 
 * 
 * Plugin supports following query parameters 
 * 									max_items=<num>		overwrite maximum number of items/movie in category provided by serviio setting  
 * 									order=desc			revers order of items.
 * 									log_level=<num>		not implemented via request. it can be change in source code. See bellow for line 
 * 														private int log_level=1
 * 														Set log level 1-10, 1 less log message, 10 maximum log message. Default log setting has to have DEBUG.
 * `													Curetly use only 1 basic, 5 midle , 10 full detail
 * example
 *http://www.ceskatelevize.cz/ivysilani/902567-bob-a-bobek-kralici-z-klobouku/200350950010013-na-ostrove?max_items=30&order=desc
 */
class CzechTV extends WebResourceUrlExtractor {

	final VALID_FEED_URL = '^http://www.ceskatelevize.cz/ivysilani/.*'
	final BASE_URL = "http://www.ceskatelevize.cz/ivysilani/"
	final AJAX_HTTP ="http://www.ceskatelevize.cz/ajax/playlistURL.php"
	
	private String useragent
	private ClientResource client
	private int log_level=1
	
	CzechTV()
	{
		useragent=getFFmpegUserAgent()
		log( "Init CzechTV user agent for http is -" + useragent);
		client=new ClientResource(org.restlet.data.Method.POST , AJAX_HTTP)
		Form requestHeaders = new Form()
		requestHeaders.add('x-addr','127.0.0.1')
		requestHeaders.add('X-Requested-With','XMLHttpRequest')
		client.getRequest().getAttributes().put("org.restlet.http.headers", requestHeaders)
	}

	void finalize()
	{
		client.release()
	}
	
	String getExtractorName() {
		return getClass().getName()
	}

	boolean extractorMatches(URL feedUrl) {
		return feedUrl ==~ VALID_FEED_URL
	}

	int getVersion()
	{
		return 1
	}

	private void my_log(int message_level,String s )
	{
		
		if(log_level>=message_level)
		{
			my_log(s)
		}
	}	
	
	private void my_log(String s)
	{
		//println s
		log(s)
	}
	WebResourceContainer extractItems(URL resourceUrl, int maxItems) {

		my_log( "Start extractItems procedure Czech TV " + resourceUrl)
		List<WebResourceItem> items = []
		
		def maxcount= resourceUrl.query=~ /(?i).*MAX_ITEMS=([0-9]+).*/
		if(maxcount.getCount()>0)
		{
		
			maxItems=maxcount[0][1].toInteger() 
		}
		boolean doreverse=resourceUrl.query==~/(?i).*ORDER=DESC.*/
		
		def page_hmlt=openURL(resourceUrl,useragent)
		
		def title = page_hmlt =~ '<title>(.*):'
		assert title.getCount() > 0, "Error not find media Title"
		my_log( "Title of Page: " + title[0][1])

		String hosturl=resourceUrl.protocol + '://' + resourceUrl.host

		def itemscount=0
		if( maxItems==-1) maxItems=Integer.MAX_VALUE //max value mean no limit

		itemscount=Add_episod_page(page_hmlt,hosturl, items, maxItems)
		if(itemscount<maxItems)
		{
			def nextpage=page_hmlt =~ '<a.*class="detailProgrammePaging next".*href="(.*)"'
			def lastpage=page_hmlt =~ '<a.*class="detailProgrammePaging last".*href="(.*)"'

			if (lastpage.getCount()>0 && nextpage.getCount()>0)
			{
				def pagenavi= nextpage[0][1]=~/.*\/([0-9]+)\/$/
				assert pagenavi.getCount() > 0, "Wrong parser /(.*)\\/([0-9]+)\\/\$/ for string" + nextpage[0][1]
				def nextpage_num=pagenavi[0][1].toInteger()

				pagenavi= lastpage[0][1]=~/(.*)\/([0-9]+)\/$/
				assert pagenavi.getCount() > 0, "Wrong parser /(.*)\\/([0-9]+)\\/\$/ for string" + lastpage[0][1]
				String baseref=pagenavi[0][1]
				def lastpage_num=pagenavi[0][2].toInteger()
				for(int i=nextpage_num ; i<=lastpage_num & itemscount<maxItems;i++ )
				{
					my_log( "next page url " + hosturl+baseref+"/"+i+"/")

					resourceUrl = new URL(hosturl+baseref+"/"+i+"/")
					page_hmlt=openURL(resourceUrl,useragent)
					
					itemscount=Add_episod_page(page_hmlt,hosturl, items, maxItems)
				}
			}
		}
		my_log( "count video files" + itemscount)
		if(doreverse)
		{
			items.reverse(true)
		}
		my_log( items.toString())
		
		return new WebResourceContainer(title: title[0][1], thumbnailUrl: items[0].getAdditionalInfo()['WebResourceItemThumbnailUrl'], items: items)
	}

	private int Add_episod_page(String page_hmlt,String hosturl,List items, int maxItems)
	{
		String WebResourceTitle = "CZECH TV"
		//println 	page_hmlt
			
		def media_list = page_hmlt =~ '<li class="itemBlock clearfix.*>.*\\s*.*<a.*href="(.*)">.*\\s*.*<img src="(.*)" alt="(.*)" width="(\\d*)" height="(\\d*)".*>'
		def media_dat = page_hmlt =~ '</h3>[.\\s]*<p>(.*)</p>'
		
		def ItemsAdded = items.size();
		if( media_list.getCount() < 1 | media_dat.getCount()<1)
		{
			my_log( "Error not find media link")
			return ItemsAdded
		}

		for( int i = 0; i < media_list.getCount() && ItemsAdded<maxItems ; i++ ) {
			my_log( "title: " + media_list[i][3]+ "\t" +  hosturl + media_list[i][1] + "\ttext date: " + media_dat[i][1] +"\tdate format: "+   new SimpleDateFormat("d. M. yyyy").parse(media_dat[i][1]).getDateString() )


			WebResourceItem item = new WebResourceItem(title: media_list[i][3],
			releaseDate: new SimpleDateFormat("d. M. yyyy").parse(media_dat[i][1]),
			additionalInfo: ['WebResourceItemUrl': hosturl + media_list[i][1],
				'WebResourceItemThumbnailUrl': media_list[i][2]
			]
			)
			items << item
			ItemsAdded++
		}

		return ItemsAdded

	}

	ContentURLContainer extractUrl(WebResourceItem item, PreferredQuality requestedQuality) {

		my_log( "-----Start extractUrl " + item.getAdditionalInfo()['WebResourceItemUrl'])

		def pageURL =new URL(item.getAdditionalInfo()['WebResourceItemUrl'])
		
		def page_hmlt=openURL(pageURL,useragent)

		String ItemVideoUrl

		//find string for request of lint to xlm play link
		def objectJSON = page_hmlt =~ 'callSOAP\\((.*)\\)'

		assert objectJSON.getCount() > 0, "Error not find media dat"

		def json = new JsonSlurper().parseText(objectJSON[0][1])
		my_log( "json"+ json)

		String str=objectJSON[0][1].toString()

		Form f=new Form()
		//		fillform(f,"","options",json )
		def options=json.options
		f.add("options[userIP]", options.userIP)
		f.add("options[playerType]", options.playerType)


		for(int j=0; j<options.playlistItems.size; j++)
		{
			def playlist=options.playlistItems[j]
			f.add("options[playlistItems][" + j + "][Type]", playlist.Type)
			f.add("options[playlistItems][" + j + "][Format]", playlist.Format)
			f.add("options[playlistItems][" + j + "][Identifier]", playlist.Identifier)
			f.add("options[playlistItems][" + j + "][Title]", playlist.Title)
			def skip=playlist.Skip
			if (skip!=null)
			{
				f.add("options[playlistItems][" + j + "][Skip][Enable]", skip.Enable.toString())
				f.add("options[playlistItems][" + j + "][Skip][Delay]", skip.Delay)
				f.add("options[playlistItems][" + j + "][ClickThruURL]", playlist.ClickThruURL)
			}
			else
			{
				f.add("options[playlistItems][" + j + "][Region]", playlist.Region)
				f.add("options[playlistItems][" + j + "][SubtitlesUrl]", playlist.SubtitlesUrl)
				f.add("options[playlistItems][" + j + "][Indexes]", playlist.Indexes)
			}

			for(int i=0; i<playlist.Gemius.Param.size; i++)
			{
				def Param=playlist.Gemius.Param[i]
				f.add("options[playlistItems][" + j + "][Gemius][Param][" + i + "][Name]", Param.Name)
				f.add("options[playlistItems][" + j + "][Gemius][Param][" + i + "][Value]", Param.Value)
			}
		}
		f.add("options[previewImageURL]", options.previewImageURL)
		f.add("options[audio]", options.audio.toString())
		f.add("options[defaultStreamQuality]", options.defaultStreamQuality)
		f.add("options[hash]", options.hash)

		my_log ( f.getQueryString())

		def res=client.post(f.getWebRepresentation(),org.restlet.data.MediaType.APPLICATION_WWW_FORM)
		my_log( "Status AJAX request: " + client.getStatus())

		String s=client.responseEntity.getText()
		s=s.replaceAll("%26", "&")

		my_log( s)

		pageURL =new URL(s)
		String page_hmlt2=openURL(pageURL,useragent)
		
		my_log (10,page_hmlt2)
		//println page_hmlt2.replace("\"", "\\\"").replace("\r\n", "\"+\r\n\"")

		Node xml = new XmlParser().parseText(page_hmlt2)

		def swichItem
		String ContentUrl
		String baseurl
		String Playpath
		
		for(int i=0;i<xml.smilRoot.body.switchItem.size();i++)
		{
			swichItem=xml.smilRoot.body.switchItem[i]

			if( ! swichItem.@'id'.contains("-AD-") )
			{
				baseurl=xml.smilRoot.body.switchItem[i].@'base'
				ContentUrl=baseurl
				
				def tmp= baseurl =~ /rtmp:\/\/.*\.cz\/(.*)/
				String app=tmp[0][1]
				
				Integer max_index=swichItem.video.size()-1
				Integer medium_index=Math.round(max_index/2.0)
					
				switch (requestedQuality) {
					case PreferredQuality.HIGH   : Playpath= swichItem.video[0].@'src' ;break;
					case PreferredQuality.MEDIUM : Playpath= swichItem.video[medium_index].@'src' ;break;
					case PreferredQuality.LOW    : Playpath= swichItem.video[max_index];break;
					default                      : Playpath= swichItem.video[medium_index].@'src' ;break;
				}

				ContentUrl= baseurl+ " app=" + app + " playpath=" + Playpath + " swfUrl=http://img9.ceskatelevize.cz/libraries/JWPlayer/player.swf swfVfy=1 live=1"
				my_log( "WebResourceItemTitle        : "+item.getTitle())
				//println "WebResourceItemId           : "+item.getAdditionalInfo()['WebResourceItemId']
				my_log(5, "WebResourceItemThumbnailUrl : "+item.getAdditionalInfo()['WebResourceItemThumbnailUrl'])
				my_log( "ContentUrl                  : "+ContentUrl)
				my_log( 10,"ffmpeg.exe -i \"" + ContentUrl + "\" out"+ (new Random().nextInt() % 600 + 1) + ".avi")
				my_log( 10,"rtmpdump -v -R -r \""+baseurl+ "\" -a \"" + app + "\" -y \"" + Playpath + "\" -s \"http://img9.ceskatelevize.cz/libraries/JWPlayer/player.swf\" -o out" + (new Random().nextInt() % 600 + 1) + ".avi")
				my_log("------ end extractUrl")
			}
		}

		return new ContentURLContainer(fileType: MediaFileType.VIDEO, contentUrl: ContentUrl, thumbnailUrl: item.getAdditionalInfo()['WebResourceItemThumbnailUrl'],cacheKey:item.getAdditionalInfo()['WebResourceItemUrl']+requestedQuality,expiresImmediately:true)

	}


	void fillform(Form f,String prefix,aaa,HashMap<String,Object> json)
	{
		def zz= json.get(aaa)
		if( zz.getClass() != java.util.HashMap.class & zz.getClass()!=java.util.ArrayList.class)
		{
			println prefix + "[" + aaa + "]=" + zz.toString()
			f.add(prefix + "[" + aaa + "]",zz.toString() )
		}
		else
		{
			println zz.getClass()
			if(prefix=="")
			{
				prefix=aaa
			}
			else
			{
				prefix+= "["+ aaa + "]"
			}
			def keys=null
			int max=0
			if (zz.getClass()==java.util.ArrayList.class)
			{
				for(int i=0;i<zz.size;i++)
				{
					if(zz[i].getClass()== java.util.HashMap.class)
					{
						def a=zz[i].keySet()
						def aa=a.toArray()
						for(int j=0; j<aa.length; j++)
						{
							fillform(f,prefix+"["+i+"]",aa[j],zz[i])
						}
					}
				}
			}
			else
			{
				keys=zz.keySet().toArray()
				for(int j=0;j<keys.length;j++)
				{
					fillform(f,prefix,keys[j],zz)
				}
			}
		}
	}





	/*********************************************
	 * MAIN
	 *********************************************/
	static void main(args) {


		def TestUrl = new URL("http://www.ceskatelevize.cz/ivysilani/10195164142-vypravej/")
		CzechTV extractor = new CzechTV()
		println "PluginName : " + extractor.getExtractorName();
		println "TestMatch  : " + extractor.extractorMatches(TestUrl);
		WebResourceContainer container = extractor.extractItems(TestUrl, 5);

		println "**** HIGH ****"  ;extractor.extractUrl(container.getItems()[1], PreferredQuality.HIGH)
		//println "**** MEDIUM ****";extractor.extractUrl(container.getItems()[3], PreferredQuality.MEDIUM)
		//println "**** LOW ****"   ;extractor.extractUrl(container.getItems()[2], PreferredQuality.LOW)
	}
}





