import groovy.util.XmlParser
import org.serviio.library.metadata.*
import org.serviio.library.online.*
import groovy.json.JsonSlurper


/********************************************************************
 * CBS.com plugin for Serviio (US ONLY)
 * Player/clip logic based on CBS Plugin for Plex
 * 
 * @author Mike_Metro
 * 
 * @updated by: X S Inattar
 * @updated on: August 25, 2012
 * updated to reflect new feed url
 *
 * Must be installed as a WebResource
 * Only available in US
 * Sample URLs: http://www.cbs.com/shows/csi/video/
 * 
 ********************************************************************/

class CBS extends WebResourceUrlExtractor {
    
    final VALID_FEED_URL = '^(?:http://)?(?:www\\.)?cbs\\.com/shows/(.*?)/video(?:/)?$'
    final SHOW_LIST = 'http://www.cbs.com/carousels/videosBySection/%s/offset/0/limit/15/'
	
    //final SHOW_LIST = 'http://www.cbs.com/carousels/videosBySection/213548/offset/0/limit/15/'
	
    // updated by: X S Inattar
    // updated on: August 25, 2012
    // begin
    //
  
    
	final PRE_SMIL_URL ='http://www.cbs.com%s'
	final SMIL_URL ='http://link.theplatform.com/s/dJ5BDC/%s?format=SMIL&Tracking=true&mbr=true'
   

    String getExtractorName() {
        return 'CBS.com'
    }
    
    boolean extractorMatches(URL feedUrl) {
        return feedUrl ==~ VALID_FEED_URL
    }
       
    WebResourceContainer extractItems(URL resourceUrl, int maxItemsToRetrieve) {
        List<WebResourceItem> items = []
		Date releaseDate
		String thumbnailUrl
        def itemsAdded = 0
		def i=0
        def pageContent = resourceUrl.getText()

        def jsMatcher = pageContent =~ "id-carousel-(.*)\" class"

        def section = jsMatcher[0][1]
		

        def contentUrl = new URL(String.format(SHOW_LIST, section))
		
        def json = new JsonSlurper().parseText(contentUrl.getText())
        
		
		for (i=0;i<Integer.valueOf(json.result.total);i++){
			thumbnailUrl=json.result.data[i].thumb.large
			
			Map<String,String> additionalInfo = new HashMap<String, String>();
			
			additionalInfo.put("ID",json.result.data[i].url)
			additionalInfo.put("thumbnailUrl",thumbnailUrl)
		
			jsMatcher = thumbnailUrl =~ "([0-9]{4})/([0-9]{2})/([0-9]{2})"
		
			releaseDate= Date.parse("yyyy/MM/dd", jsMatcher[0][0])
			
			items << new WebResourceItem(title: json.result.data[i].title,releaseDate: releaseDate,additionalInfo: additionalInfo)
		}
		
		
        def nameMatcher = resourceUrl.toString() =~ VALID_FEED_URL
        def showTitle = nameMatcher[0][1] 
		
        return new WebResourceContainer(title: showTitle, items: items)
    }

    ContentURLContainer extractUrl(WebResourceItem item, PreferredQuality requestedQuality) {
		
        def pageContent = new URL(String.format(PRE_SMIL_URL , item.additionalInfo.ID)).getText()
	
		
		def PID = pageContent =~ "video.settings.pid = '(.*)';" 
		
		def smil = new URL(String.format(SMIL_URL, PID[0][1])).getText()
		
        // xml parser/slurper had issues was decoding encoded characters &amp; etc.   
	
		
       // updated by: X S Inattar
       // updated on: August 25, 2012
       // begin
       //
       def stream_source_matcher = smil =~ 'meta base="(.*?)"'
       if (stream_source_matcher.count <= 0) {
           return null
       }
	   
       def stream_source = stream_source_matcher[0][1]    
		//println stream_source       
       // end
        
        def vidMatcher = smil =~ 'video src="(.*?)".*?system-bitrate="(.*?)"'
        def player
        def formats = [:]        

        for (i in 0..<vidMatcher.count) {
            formats[vidMatcher[i][2].padLeft(10,"0")] = vidMatcher[i][1]
        }

        Comparator comparator = [compare: {a , b ->
            b.compareTo(a)
        }] as Comparator

        formats = formats.sort(comparator)
        def keys = formats.keySet().toList()

        if (requestedQuality == PreferredQuality.HIGH || formats.count == 1) {
            player = formats[keys[0]]        
        }    
        else if (requestedQuality == PreferredQuality.MEDIUM || formats.count == 2) {
            player = formats[keys[1]] 
        }
        else if (requestedQuality == PreferredQuality.LOW) {
            player = formats[keys[2]] 
        }    

        // updated by: X S Inattar
        // updated on: August 25, 2012
        // begin
        //
        //def clip = []        
        def clip = ''
        
        if (player.contains('.mp4')) { 
            player = player.replace('.mp4', '')
            //clip = player.split(';')
            //clip = 'mp4:' + clip[4]
            clip = 'mp4:' + player
        }
        else if (player.contains('.flv')) {
            player = player.replace('.flv', '')
            //clip = player.split(';')
            //clip = clip[4]
            clip = player
        }
        //def contentUrl = "${player} playpath=${clip}"
        def contentUrl = "${stream_source} playpath=${clip}"
        // end
        
        def cacheKey = "CBS_${item.additionalInfo.PID}_${requestedQuality}"
        return new ContentURLContainer(contentUrl: contentUrl, thumbnailUrl: item.additionalInfo.thumbnailUrl, expiresImmediately: true, cacheKey : cacheKey)    
    }
    
    static void main(args) {
        CBS extractor = new  CBS()
       
        WebResourceContainer container = extractor.extractItems( new URL("http://www.cbs.com/shows/csi/video/"), 4)
		 
        container.getItems().each {
			
            ContentURLContainer result = extractor.extractUrl(it, PreferredQuality.MEDIUM)
            println result 
        }   
    }
}