import groovy.util.XmlParser
import org.serviio.library.metadata.*
import org.serviio.library.online.*
import groovy.json.JsonSlurper


/********************************************************************
 * PBS Kids plugin for Serviio
 * Logic based on XBMC -> BlueCop Repo -> Free Cable -> PBS Kids
 * 
 * @author X S Inattar
 *
 * Must be installed as a Video WebResource
 * Sample URLs: 
 *    http://pbskids.org/video/Curious%20George
 *    http://pbskids.org/video/Angelina Ballerina
 * 
 * Version:
 *    V1: August 17, 2012 - Initial Release
 *	  V2: August 19, 2012 - Bug fix: video stops abruptly
 *
 ********************************************************************/

class PBSKids extends WebResourceUrlExtractor {

    final VALID_RESOURCE_URL = '^(?:http://)?(?:www\\.)?pbskids\\.org/video/(.*?)$'
    
    final CLIPS_FEED_URL_PART_1 = 'http://pbs.feeds.theplatform.com/ps/JSON/PortalService/2.2/getReleaseList?PID=6HSLquMebdOkNaEygDWyPOIbkPAnQ0_C&startIndex=1'
    final CLIPS_FEED_URL_PART_2 = '&sortField=airdate&sortDescending=true&query=Categories|'
    final CLIPS_FEED_URL_PART_3 = '&field=title&field=expirationDate&field=thumbnailURL&field=URL&field=PID&contentCustomField=IsClip&contentCustomField=RelatedContentIDs&contentCustomField=RelatedContentIDs_Spanish&contentCustomField=Related_Activities&contentCustomField=Series_URL&contentCustomField=TV_Rating&contentCustomField=Production_NOLA&contentCustomField=Series_Title&contentCustomField=IsGame_header&contentCustomField=Episode_Title&query=CustomBoolean|isPreschool|true&param=affiliate|PBS%20KIDS%20NATIONAL&param=player|PreKplayer'            
    
    final BASE_MATCHER = '<meta base="(.*?)" />'
    final SOURCE_MATCHER = '<ref src="(.*?)" title="'

    String getExtractorName() {
        return 'pbskids.org'
    }
    
    boolean extractorMatches(URL resourceUrl) {
        return resourceUrl ==~ VALID_RESOURCE_URL
    }
       
    WebResourceContainer extractItems(URL resourceUrl, int maxItemsToRetrieve) {
    
        def show_title_extractor = resourceUrl =~ VALID_RESOURCE_URL
        if (show_title_extractor.count <= 0) {
            return null
        }
        def showTitle = show_title_extractor[0][1]
        showTitle = showTitle.replaceAll('%20',' ')
        def showFeedTitle = showTitle.replaceAll(' ','%20')
        
        def clips_feed_url = CLIPS_FEED_URL_PART_1
        if (maxItemsToRetrieve >= 0) {
            clips_feed_url = clips_feed_url + '&endIndex=' + maxItemsToRetrieve
        } 
        clips_feed_url = clips_feed_url + CLIPS_FEED_URL_PART_2 + showFeedTitle + CLIPS_FEED_URL_PART_3
        
        def clips_feed_text = new URL(clips_feed_url).getText()
        def json = new JsonSlurper().parseText(clips_feed_text)
        
        if (json.listInfo.itemCount <= 0) {
            return null
        }
        
        List<WebResourceItem> items = []
        json.items.find {
             items << new WebResourceItem(
                    title: it.title,
                    additionalInfo: [PID: it.PID, thumbnailURL: it.thumbnailURL, smilURL: it.URL + '&format=smil' ]
                )
             return false
        }
        

        return new WebResourceContainer(title: showTitle, items: items)
    }

    ContentURLContainer extractUrl(WebResourceItem item, PreferredQuality requestedQuality) {        

        def smilText = new URL(item.additionalInfo.smilURL).getText()
        
        def base_extractor = smilText =~ BASE_MATCHER
        if (base_extractor.count < 0) {
            return null
        }
        def base_url = base_extractor[0][1]
        
        def source_extractor = smilText =~ SOURCE_MATCHER
        if (source_extractor.count < 0) {
            return null
        }
        def source_url = source_extractor[0][1]
        
        def contentUrl =""
        if (base_url.startsWith("rtmp://") ) {
            if (source_url.contains('.mp4')) {                 
                source_url = 'mp4:' + source_url
            }
            else if (source_url.contains('.flv')) {
                source_url = source_url.replace('.flv', '')
            }
            contentUrl = base_url + ' playpath=' + source_url
        }
        else if (base_url.startsWith("http://")) {
            contentUrl = base_url + source_url
        }
        else {
            return null
        }                                
        
        def cacheKey = "PBSKids_" + item.additionalInfo.PID
       
        return new ContentURLContainer(contentUrl: contentUrl, thumbnailUrl: item.additionalInfo.thumbnailURL, expiresImmediately: true, cacheKey : cacheKey)    
    }
        
    static void main(args) {
        PBSKids extractor = new  PBSKids()
        
        WebResourceContainer container = extractor.extractItems( new URL("http://pbskids.org/video/Curious%20George"), 1)
        container.getItems().each {
            ContentURLContainer result = extractor.extractUrl(it, PreferredQuality.MEDIUM)
            println result
        }   
        
        container = extractor.extractItems( new URL("http://pbskids.org/video/Angelina Ballerina"), 1)
        container.getItems().each {
            ContentURLContainer result = extractor.extractUrl(it, PreferredQuality.MEDIUM)
            println result
        }   
    }
}