import org.serviio.library.metadata.*
import org.serviio.library.online.*
import static org.apache.commons.lang.StringEscapeUtils.*

 /********************************************************************
 * Disney.com plugin for Serviio (US ONLY)
 * 
 *
 * Version:
 *    V1: - Initial Release by nwalk7800
 *    V2: - Won't die if Wikia page doesn't exist
 *    V3: - Disney switch to a flash based player with encrypted_hls
 *
 * Must be installed as a WebResource
 * Only available in US
 * Sample URLs: http://disneychannel.disney.com/austin-and-ally/video
  ********************************************************************/

class Disney extends WebResourceUrlExtractor {
    
    final VALID_FEED_URL = '^(?:http://)?(?:disneychannel\\.)?disney\\.com/(.*?)(/|-)video(?:/)?$'
    final PRE_SMIL_URL ='http://cdn.videos.dolimg.com/%s'
    final CONTENT_INFO = '<div class=\"thumbnail\">.*?(http://video\\.disney\\.com/watch/disneychannel-.*?)\".*?<img src=\"(.*?)\".*?alt=\"(.*?)\".*?<h4>(.*?)</h4>'
    final WIKIA_INFO = '(?i)%s.*?</td><td>.*?(\\w*? \\d{1,2}, \\d{4})<'
    final WIKIA_URL = 'disneychannel.disney.com/(.*?)(/|-)video'
    
    int getVersion()
    {
        return 3
    }
    
    int getExtractItemsTimeout()
    {
        return 30
    }
    
    WebResourceContainer errorHandlerWRC(String e)
    {
        List<WebResourceItem> items = []
        println e
        log(e)
        items <<  new WebResourceItem(title: e, additionalInfo: ['url':'http://error','thumbnailUrl':'http://fake.jpg'])
        WebResourceContainer wrc = new WebResourceContainer(title: "Error", items: items)
        return wrc
    }
    
    void errorHandler(String e)
    {
        println e
        log(e)
        return 
    }

    String getExtractorName()
    {
        return 'Disney.com'
    }
    
    boolean extractorMatches(URL feedUrl)
    {
        return feedUrl ==~ VALID_FEED_URL
    }
       
    WebResourceContainer extractItems(URL resourceUrl, int maxItemsToRetrieve)
    {
        List<WebResourceItem> items = []
        Date releaseDate
        def showTitle
        def strEpTitle
        def section
        def pageContent
        def jsMatcher
        def wikiaContent
        def mWikia
        
        pageContent = resourceUrl.getText()
        pageContent = pageContent.replaceAll("\n", "")
        
        try
        {
            wikiaContent = new URL(getWikiaURL(resourceUrl)).getText()
            wikiaContent = wikiaContent.replaceAll("\n", "")
        }
        catch(e){}
        
        jsMatcher = pageContent =~ CONTENT_INFO
        
        if (jsMatcher.count <= 0)
        {
           return errorHandler("Disney: No items found")
        }
        
        section = jsMatcher[0][1]
        
        //try
        //{
            for (def i = 0; i < jsMatcher.count; i++)
            {
                Map<String,String> additionalInfo = new HashMap<String, String>();
            
                additionalInfo.put("url", jsMatcher[i][1])
                additionalInfo.put("thumbnailUrl", jsMatcher[i][2])
        
                showTitle = jsMatcher[i][4]
                strEpTitle = jsMatcher[i][3].replaceAll(".*?: ", "")

                //Get release date from Wikia
                mWikia = wikiaContent =~ String.format(WIKIA_INFO, strEpTitle)
                if (mWikia.count > 0)
                    releaseDate=Date.parse("MMM dd, yyyy", mWikia[0][1])
                else
                    releaseDate = new Date()

                showTitle = unescapeHtml(showTitle)
                strEpTitle = unescapeHtml(strEpTitle)

                //Get the air date from thetvdb.com, requires api key
                //releaseDate = getAirDate(showTitle, strEpTitle)
                
                items << new WebResourceItem(title: strEpTitle, releaseDate: releaseDate, additionalInfo: additionalInfo)
            }
        //}
        //catch(e)
        //{
        //    errorHandler("Disney: Error parsing items")
        //}
        
        return new WebResourceContainer(title: showTitle, items: items)
    }

    String getWikiaURL(URL url)
    {
        def mTitle
        def strTitle
        def retval
        
        mTitle = url =~ WIKIA_URL
        
        switch (mTitle[0][1])
        {
            case "austin-and-ally":
                retval = "http://austinally.wikia.com/wiki/Episode_Guide"
                break
            case "dog-with-a-blog":
                retval = "http://dogwithablog.wikia.com/wiki/List_of_Dog_With_a_Blog_episodes"
                break
            default:
                strTitle = mTitle[0][1].replaceAll("-", "")
                retval = "http://${strTitle}.wikia.com/wiki/Episode_Guide"
        }
        return retval
    }

    ContentURLContainer extractUrl(WebResourceItem item, PreferredQuality requestedQuality)
    {
        def episodeURL
        def pageContent
        def contentURL
        def cacheKey
        def epMatcher
        
        //Get episode mp4 URL
        episodeURL =  new URL(item.additionalInfo.url)
        try
        {
            pageContent = episodeURL.getText()
        }
        catch (FileNotFoundException e)
        {
            errorHandler("Disney: Episode URL not found")
        }
        
        //Get the correct quality
        if (requestedQuality == PreferredQuality.HIGH)
            epMatcher = pageContent =~ "(mp4:.*?848x480.*?\\.mp4)\""
        else if (requestedQuality == PreferredQuality.MEDIUM)
            epMatcher = pageContent =~ "(mp4:.*?480x320.*?\\.mp4)\""
        else if (requestedQuality == PreferredQuality.LOW)
            epMatcher = pageContent =~ "(mp4:.*?480x320.*?\\.mp4)\""
        
        println episodeURL
        
        //Get the url to the content
        if (epMatcher.count > 0)
        {
            contentURL = "rtmp://videodolimgfs.fplive.net/videodolimg"
            contentURL += " app=videodolimg "
            contentURL += " playpath=" + epMatcher[0][1]
            contentURL += " swfVfy=http://a.dilcdn.com/a/playavista-14701b504ff4.swf"
            cacheKey = "Disney_${item.additionalInfo.PID}_${requestedQuality}"
        }

        //return new ContentURLContainer(contentUrl: String.format(PRE_SMIL_URL , contentURL), thumbnailUrl: item.additionalInfo.thumbnailUrl, expiresImmediately: true, cacheKey : cacheKey)    
        return new ContentURLContainer(contentUrl: contentURL, thumbnailUrl: item.additionalInfo.thumbnailUrl, cacheKey : cacheKey)    
    }
        
    Date getAirDate(String strSeries, String strEpisode)
    {
        def strURL = "http://thetvdb.com/api/"
        def strSeriesLookup = "%sGetSeries.php?seriesname=%s"
        def strSeriesXML = "%s%s/series/%s/all/en.xml"
        def strAPI = "Your api key here"
        def strSeriesRegex = "(?i)<seriesid>(\\d*?)<\\/seriesid><language>en<\\/language><SeriesName>%s<\\/SeriesName>"
        def strEpisodeRegex = "(?i)<%s>\\s*(?:the )?%s\\s*<\\/%s>.*?<FirstAired>(.*?)<\\/FirstAired>"
        def mSeries
        def strContents
        def blnNumbered = false
        def dtmRetval = new Date()

        //Check to see if this is a numbered episode
        mSeries = strEpisode =~ "(?i)Episode (\\d{1,3})"
        if (mSeries.count > 0)
        {
            strEpisode = mSeries[0][1]
            blnNumbered = true
        }

        //Lookup series id
        strContents = new URL(String.format(strSeriesLookup, strURL, strSeries.replaceAll(" ", "%20"))).getText().replaceAll("\n", "")
        mSeries = strContents =~ String.format(strSeriesRegex, escapeHtml(strSeries))
        
        if (mSeries.count > 0)
        {
            //Lookup air date
            strContents = new URL(String.format(strSeriesXML, strURL, strAPI, mSeries[0][1])).getText().replaceAll("\n", "")
            
            if (blnNumbered)
                mSeries = strContents =~ String.format(strEpisodeRegex, "EpisodeNumber", escapeHtml(strEpisode), "EpisodeNumber")
            else
                mSeries = strContents =~ String.format(strEpisodeRegex, "EpisodeName", escapeHtml(strEpisode), "EpisodeName")
                       
            if (mSeries.count > 0)
                dtmRetval = Date.parse("yyyy-MM-dd", mSeries[0][1])
        }
        return dtmRetval
    }
    
    static void main(args)
    {
        Disney extractor = new  Disney()
        //for testing

        //WebResourceContainer container = extractor.extractItems(new URL("http://disneychannel.disney.com/austin-and-ally/video"), 5)
        WebResourceContainer container = extractor.extractItems(new URL("http://disneychannel.disney.com/jessie/video"), 5)
        //WebResourceContainer container = extractor.extractItems(new URL("http://disneychannel.disney.com/shake-it-up/video"), 5)
        //WebResourceContainer container = extractor.extractItems(new URL("http://disneychannel.disney.com/good-luck-charlie/video"), 5)
        //WebResourceContainer container = extractor.extractItems(new URL("http://disneychannel.disney.com/ant-farm/video"), 5)
        //WebResourceContainer container = extractor.extractItems(new URL("http://disneychannel.disney.com/dog-with-a-blog-video"), 5)
        //WebResourceContainer container = extractor.extractItems(new URL("http://disneychannel.disney.com/phineas-and-ferb/video"), 5)
        
        if (container)
        {
            container.getItems().each
            {
                ContentURLContainer result = extractor.extractUrl(it, PreferredQuality.HIGH)
                println it
                println result
                println ""
            }
        }   
    }
}