import groovy.util.XmlParser
import org.serviio.library.metadata.*
import org.serviio.library.online.*
import groovy.json.JsonSlurper


/********************************************************************
 * CW plugin for Serviio
 * Logic based on XBMC -> BlueCop Repo -> Free Cable -> The CW
 * 
 * @author X S Inattar
 *
 * Must be installed as a Video WebResource
 * Sample URLs: 
 *    http://www.cwtv.com/cw-video/supernatural/
 *    http://www.cwtv.com/cw-video/the-vampire-diaries/
 * 
 * Version:
 *    V1: June 29, 2012 - Initial Release
 *    V2: October 12, 2012 - 
 *
 ********************************************************************/

class CW extends WebResourceUrlExtractor {
    
    final VALID_FEED_URL = '^(?:http://)?(?:www\\.)?cwtv\\.com/cw-video/(.*?)(?:/)?$'
    final FULL_EPISODE_ID_EXTRACTOR = '<div class="videowrapped slide full-episodes.*?<a class="thumbLink" href="/cw-video/.*?/.*?/?play=(.*?)".*?<img src="(.*?)"'
    final FULE_EPISODE_INFO_URL = 'http://metaframe.digitalsmiths.tv/v2/CWtv/assets/%s/partner/132?format=json'
    final SWF_URL = 'http://pdl.warnerbros.com/cwtv/digital-smiths/production_player/vsplayer.swf'

    String getExtractorName() {
        return 'cwtv.com'
    }
    
    boolean extractorMatches(URL feedUrl) {
        return feedUrl ==~ VALID_FEED_URL
    }
       
    WebResourceContainer extractItems(URL resourceUrl, int maxItemsToRetrieve) {
            
        List<WebResourceItem> items = []
        def itemsAdded = 0

        def nameMatcher = resourceUrl.toString() =~ VALID_FEED_URL
        def showTitle = nameMatcher[0][1]                
        
        Comparator comparator = [compare: {a , b ->
            b.compareTo(a)
        }] as Comparator
        
        def showPageText = resourceUrl.getText()
        showPageText = showPageText.replaceAll("\n", "")
        def episodeIds = showPageText =~ FULL_EPISODE_ID_EXTRACTOR
        def contentUrl
        def episodeId
        def thumbUrl
        def contentText
        def json
        def seriesTitleSet = false
        def loopRun = (maxItemsToRetrieve != -1 && maxItemsToRetrieve <= episodeIds.count) ? maxItemsToRetrieve : episodeIds.count
        for (i in 0..<loopRun) {
            episodeId = episodeIds[i][1]
            thumbUrl = episodeIds[i][2]
            contentUrl = new URL(String.format(FULE_EPISODE_INFO_URL,episodeId))            
            contentText = contentUrl.getText()
            json = new JsonSlurper().parseText(contentText)            
            if (!seriesTitleSet) {
                showTitle = json.assetFields.seriesName
                seriesTitleSet = true
            }
            def episodeTitle = json.assetFields.title
            def airDate = json.assetFields.originalAirDate            
            def clip_QUALITY_HIGH = ""
            def clip_QUALITY_MEDIUM = ""
            def clip_QUALITY_LOW = ""
            
            def videosByBitrate = [:]
            json.videos.find {
                def videoItem = it.toString()
                def videoBitrateMatcher = videoItem =~ 'bitrate=(.*?),'
                def videoBitrate = videoBitrateMatcher[0][1]
                def videoUriMatcher = videoItem =~ 'uri=(.*?)}'
                def videoUri = videoUriMatcher[0][1]
                videosByBitrate[videoBitrate] = videoUri   
                return false
            }
            videosByBitrate = videosByBitrate.sort(comparator)
            def keys = videosByBitrate.keySet().toList()
            def videosCount = videosByBitrate.size()
            if (videosCount == 1) {
                clip_QUALITY_HIGH = videosByBitrate[keys[0]]
                clip_QUALITY_MEDIUM = videosByBitrate[keys[0]]
                clip_QUALITY_LOW = videosByBitrate[keys[0]]
            }    
            else if (videosCount == 2) {
                clip_QUALITY_HIGH = videosByBitrate[keys[0]]
                clip_QUALITY_MEDIUM = videosByBitrate[keys[1]]
                clip_QUALITY_LOW = videosByBitrate[keys[1]]
            }
            else {
                clip_QUALITY_HIGH = videosByBitrate[keys[0]]
                clip_QUALITY_MEDIUM = videosByBitrate[keys[1]]
                clip_QUALITY_LOW = videosByBitrate[keys[2]]
            }            
            items << new WebResourceItem(title: episodeTitle, releaseDate: new Date().parse("yyyy-MM-dd", airDate), additionalInfo: [GUID: episodeId, thumbnailUrl: thumbUrl, contentUrl_QUALITY_HIGH: clip_QUALITY_HIGH, contentUrl_QUALITY_MEDIUM: clip_QUALITY_MEDIUM, contentUrl_QUALITY_LOW: clip_QUALITY_LOW] )                
        }
        
        return new WebResourceContainer(title: showTitle, items: items)
    }

    ContentURLContainer extractUrl(WebResourceItem item, PreferredQuality requestedQuality) {
                
        def contentUrl = ""
        
        if (requestedQuality == PreferredQuality.HIGH) {
            contentUrl = item.additionalInfo.contentUrl_QUALITY_HIGH       
        }    
        else if (requestedQuality == PreferredQuality.MEDIUM) {
            contentUrl = item.additionalInfo.contentUrl_QUALITY_MEDIUM
        }
        else if (requestedQuality == PreferredQuality.LOW) {
            contentUrl = item.additionalInfo.contentUrl_QUALITY_LOW     
        }                
        
        def clip = contentUrl.split("mp4:")
        contentUrl = clip[0] + " playpath=mp4:" + clip[1] + " swfUrl=" + SWF_URL
        def cacheKey = "CW_${item.additionalInfo.GUID}_${requestedQuality}"
       
        return new ContentURLContainer(contentUrl:  contentUrl, thumbnailUrl: item.additionalInfo.thumbnailUrl, expiresImmediately: true, cacheKey : cacheKey)    
    }
        
    static void main(args) {
    
        CW extractor = new  CW()
        
        WebResourceContainer container = extractor.extractItems( new URL("http://www.cwtv.com/cw-video/supernatural/"), 20)
        container.getItems().each {
            ContentURLContainer result = extractor.extractUrl(it, PreferredQuality.MEDIUM)
            println result 
        }   
    }
}