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/%s/video/%s/%s/0/100/'
    
    // updated by: X S Inattar
    // updated on: August 25, 2012
    // begin
    //
    // old feed url
    // final SMIL_URL = 'http://release.theplatform.com/content.select?format=SMIL&Tracking=true&balance=true&MBR=true&pid=%s'    
    // new feed url
    final SMIL_URL = 'http://link.theplatform.com/s/dJ5BDC/%s?format=SMIL&Tracking=true&mbr=true'
    //
    // end

    String getExtractorName() {
        return 'CBS.com'
    }
    
    boolean extractorMatches(URL feedUrl) {
        return feedUrl ==~ VALID_FEED_URL
    }
       
    WebResourceContainer extractItems(URL resourceUrl, int maxItemsToRetrieve) {
        List<WebResourceItem> items = []
        def itemsAdded = 0
        
        def pageContent = resourceUrl.getText()
        def jsMatcher = pageContent =~ "loadUpCarousel\\('(.*?)','(.*?)', '(.*?)', (.*?),"
        def section = jsMatcher[0][2]
        def vidHash = jsMatcher[0][3]
        def showId = jsMatcher[0][4]

        def contentUrl = new URL(String.format(SHOW_LIST, showId, section, vidHash))
        def json = new JsonSlurper().parseText(contentUrl.getText())

        json.itemList.find { 
            items << new WebResourceItem(title: it.label, releaseDate: new Date(it.airDate.toLong()), additionalInfo: [PID:it.pid, thumbnailUrl: it.thumbnail])
            itemsAdded++
            if (maxItemsToRetrieve != -1 && itemsAdded >= maxItemsToRetrieve) return true
            return false
        }

        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 smil = new URL(String.format(SMIL_URL, item.additionalInfo.PID)).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]           
       // 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/"), 5)
        container.getItems().each {
            ContentURLContainer result = extractor.extractUrl(it, PreferredQuality.MEDIUM)
            println result 
        }   
    }
}