import groovy.util.XmlParser
import groovy.json.JsonSlurper
import org.serviio.library.metadata.*
import org.serviio.library.online.*
import org.serviio.util.*

/********************************************************************
 * cricfree.tv plugin for Serviio
 * 
 * @author X S Inattar
 *
 * URL to use as video webresource: http://www.cricfree.tv/
 * 
 * Version:
 *    V1: - Sep 28, 2012 - Initial Release
 *    V2: - Sep 30, 2012 - Added support for fcast.tv
 *    V3: - Oct 08, 2012 - Added support for castamp.tv, castup.tv
 *
 ********************************************************************/
 
 class CricFreeTV extends WebResourceUrlExtractor {
 
    final VALID_RESOURCE_URL = '^(?:http://)?(?:www\\.)?cricfree.tv/'
    final BASE_URL = 'http://www.cricfree.tv'
    final BASE_IMAGE_URL = 'https://sites.google.com/site/cricfreetvimages'
    final TITLE = 'CRICFREE.TV'
    final CHANNEL_LIST_EXTRACTOR = '<li class="level1"><a href="(.*?)" class="level1"><img src="/images(.*?)" width="120" height="23" align="center" border="0" alt=""/></a></li>'
    
    
    String getExtractorName() {
        return 'cricfree.tv'
    }
    
    boolean extractorMatches(URL resourceURL) {
        return resourceURL ==~ VALID_RESOURCE_URL
    }
   
    /**/
    void write_to_log(
        String text
    ) {
        log(TITLE + ' - ' + text)
    }
    /**/
    
    Boolean URLExists(URL fileURL){
        if(((HttpURLConnection) fileURL.openConnection()).getResponseCode() == 404){
            return false
        }
        return true
    }
    
    Boolean channelOffline(
        String htmlText, 
        String offlineChecker
    ) {        
        def offline_check = htmlText =~ offlineChecker
        if (offline_check.count > 0) {
            return true
        }
        return false
    }         
    
    Boolean streamNotSupported(
        String htmlText, 
        String streamNotSupportedChecker
    ) {        
        def notsupported_check = htmlText =~ streamNotSupportedChecker
        if (notsupported_check.count > 0) {
            return true
        }
        return false
    }
    
    String modify_playpath_based_on_page_url(String playpath, String pageURL) {
        def actual_playpath = playpath                
        
        return actual_playpath
    }
    
    String modify_playpath_based_on_swf_url(String playpath, String swfURL) {
        def actual_playpath = playpath
        
        return actual_playpath
    }
    
    String fix_playpath(String playpath) {
        def actual_playpath = playpath
        
        actual_playpath = actual_playpath.replaceAll(".flv", "")
        actual_playpath = java.net.URLDecoder.decode(actual_playpath)
        
        return actual_playpath
    } 
        
    String redirect_to_actual_stream(String stream) {
        def actual_stream = stream        
        
        return actual_stream
    }
    
    String modify_stream_based_on_page_and_playpath(String stream, String pageURL, String playpath) {
        def actual_stream = stream                
                
        return actual_stream
    }
    
    String modify_stream_based_on_swf_url(String stream, String swfURL) {
        def actual_stream = stream               
        
        return actual_stream
    }  
    
    String process_for_URL(        
        String htmlText,
        String rgxMatcher,
        String baseURL
    ) {       
        def return_val = '-NOTFOUND-'        
        def matcher = htmlText =~ rgxMatcher
        if (matcher.count > 0) {
            return_val = '-URL-' + baseURL + matcher[0][1]
        }        
        return return_val
    }
    
    String process_for_PLAYPATH(
        String htmlText,
        String rgxMatcher,
        String[] streamURLs,
        String baseURL,
        String swfURL        
    ) {        
        def return_val = '-NOTFOUND-'        
        def matcher = htmlText =~ rgxMatcher
        if (matcher.count > 0) {
            
            def pageURL = baseURL + matcher[0][1]
            
            def playpath = fix_playpath(matcher[0][1])            
            
            def stream = streamURLs[ (int)(System.currentTimeMillis() % streamURLs.size()) ]
            stream = modify_stream_based_on_page_and_playpath(stream, pageURL, playpath)
            
            playpath = modify_playpath_based_on_page_url(playpath, pageURL)
            playpath = modify_playpath_based_on_swf_url(playpath, swfURL)
            
            return_val = '-STREAM-' + stream
            return_val = return_val + ' playpath=' + playpath
            return_val = return_val + ' pageUrl=' + pageURL
            return_val = return_val + ' swfUrl=' + swfURL
            return_val = return_val + ' live=1'
        }        
        return return_val
    }
    
    String process_for_SWF_PLAYPATH_STREAMER(
        String htmlText,
        String rgxMatcher,
        String pageUrl,
        String swfUrlPostfix
    ) {        
        def return_val = '-NOTFOUND-'        
        def matcher = htmlText =~ rgxMatcher
        if (matcher.count > 0) {
            
            def swfUrl = matcher[0][1] + swfUrlPostfix
            def playpath = fix_playpath(matcher[0][2])
            def stream = matcher[0][3]
            stream = modify_stream_based_on_page_and_playpath(stream, pageUrl, playpath)
            stream = modify_stream_based_on_swf_url(stream, swfUrl)
            stream = redirect_to_actual_stream(stream)
            
            playpath = modify_playpath_based_on_page_url(playpath, pageUrl)
            playpath = modify_playpath_based_on_swf_url(playpath, swfUrl)
            
            return_val = '-STREAM-' + stream
            return_val = return_val + ' playpath=' + playpath
            return_val = return_val + ' pageUrl=' + pageUrl
            return_val = return_val + ' swfUrl=' + swfUrl
            return_val = return_val + ' live=1'
        }        
        return return_val
    }
    
    String processChannel(
        String channel_url
    )
    {
        def log_text = ''
        def error = ''   
        
        if (!URLExists(new URL(channel_url))) {
            error = '-DEADLINK-'
            log_text = log_text + error
            print error
            write_to_log(log_text)
            return error
        }
        def channel_src_text = openURL( new URL(channel_url),
            "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.83 Safari/537.1"
            )        
        channel_src_text = channel_src_text.replaceAll('%3A',':')
        channel_src_text = channel_src_text.replaceAll('%2F','/')
        channel_src_text = channel_src_text.replaceAll('&amp;','&')                                         
        channel_src_text = channel_src_text.replaceAll('&quot;','"')                                         
        channel_src_text = channel_src_text.replaceAll('&lt;','<')                                         
        channel_src_text = channel_src_text.replaceAll('&gt;','>')                                                                 
        channel_src_text = channel_src_text.replaceAll('%2D','-')
        
        def channel_stream_url_text = channel_src_text            
        def url_found = 0          
        def loop = 0  
        def base_url = ''
        def current_url = channel_url //channel_src
        def rtmp_url = ''            
        while (url_found == 0) {
        
            if (channelOffline(channel_stream_url_text, '<h1 class="center">This channel is offline\\.</h1>')
                || channelOffline(channel_stream_url_text, '<h4 class=.*?THIS CHANNEL IS CURRENTLY OFFLINE</h4>')
                ) {
                error = '-OFFLINE-'
                log_text = log_text + error
                print error
                write_to_log(log_text)
                return error
            }
            
            if (streamNotSupported(channel_stream_url_text, '<media url="rtmfp://.*?/>')
                || streamNotSupported(channel_stream_url_text, '<script.*?src=".*?player\\.ooyala\\.com.*?"></script>')                    
                ) {
                error = '-NOTSUPPORTED-'
                log_text = log_text + error
                print error
                write_to_log(log_text)
                return error
            }
            
            def returned_url = '-NOTFOUND-'     
            
            if (returned_url == '-NOTFOUND-') {
                returned_url = process_for_PLAYPATH(
                    channel_stream_url_text,
                    '<script.*?fid="(.*?)".*?src=".*?yycast\\.com.*?"></script>',
                    (String[])[    
                        'rtmp://188.122.86.207:1935/live',
                        'rtmp://188.122.86.234:1935/live',
                        'rtmp://188.122.86.230:1935/live'
                    ],
                    'http://www.yycast.com/embed.php?fileid=',
                    'http://cdn.yycast.com/player/player.swf'
                )
            }
            
            if (returned_url == '-NOTFOUND-') {
                returned_url = process_for_PLAYPATH(
                    channel_stream_url_text,
                    "javascript:popUp.*?yycast\\.com/(.*?)'\\)",
                    (String[])[    
                        'rtmp://188.122.86.207:1935/live',
                        'rtmp://188.122.86.234:1935/live',
                        'rtmp://188.122.86.230:1935/live'
                    ],
                    'http://www.yycast.com/embed.php?fileid=',
                    'http://cdn.yycast.com/player/player.swf'
                )
            }       
            
            if (returned_url == '-NOTFOUND-') {
                returned_url = process_for_PLAYPATH(
                    channel_stream_url_text,
                    "<script.*?channel='(.*?)'.*?src='.*?liveflash\\.tv.*?'></script>",
                    (String[])[    
                        'rtmp://208.43.175.45/stream',
                        'rtmp://31.204.154.63/stream',
                        'rtmp://108.170.10.2/stream'
                    ],
                    'http://www.liveflash.tv/embedplayer/',
                    'http://www.liveflash.tv/resources/scripts/eplayer.swf'
                )
            } 
            
            if (returned_url == '-NOTFOUND-') {
                returned_url = process_for_PLAYPATH(
                    channel_stream_url_text,
                    "onClick=\"javascript:popUp\\('.*?liveflash\\.tv/(.*?)'\\)\"></a><a.*?></a><a.*?><img.*?></a>",
                    (String[])[    
                        'rtmp://208.43.175.45/stream',
                        'rtmp://31.204.154.63/stream',
                        'rtmp://108.170.10.2/stream'
                    ],
                    'http://www.liveflash.tv/embedplayer/',
                    'http://www.liveflash.tv/resources/scripts/eplayer.swf'
                )
            } 
            
            if (returned_url == '-NOTFOUND-') {
                returned_url = process_for_PLAYPATH(
                    channel_stream_url_text,
                    '<script.*?channel="(.*?)".*?src=".*?castamp\\.com.*?"></script>',
                    (String[])[    
                        'rtmp://68.68.31.224/live',
                        'rtmp://s31.castamp.com/live'
                    ],
                    'http://www.castamp.com/embed.php?c=',
                    'http://www.udemy.com/static/flash/player5.9.swf'
                )
            }
            
            if (returned_url == '-NOTFOUND-') {
                returned_url = process_for_PLAYPATH(
                    channel_stream_url_text,
                    '<script.*?fid="(.*?)"; v_width=.*?src=".*?castup\\.tv.*?"></script>',
                    (String[])[    
                        'rtmp://95.211.191.35:80/live',
                        'rtmp://95.211.185.39:80/live',
                        'rtmp://95.211.185.40:80/live'
                    ],
                    'http://www.castup.tv/embed.php?u=',
                    'http://i1168.photobucket.com/albums/r496/castuptv/player.swf'
                )
            }
            
            if (returned_url == '-NOTFOUND-') {
                returned_url = process_for_URL(
                    channel_stream_url_text,
                    "<script.*?fid='(.*?)';.*?src='.*?fcast\\.tv",
                    'http://www.fcast.tv/embed.php?live='
                )
                
                if (returned_url.contains("-URL-")) {
                    String temp_returned_url = returned_url
                    temp_returned_url = temp_returned_url.replaceFirst("-URL-","")
                    if (!URLExists(new URL(temp_returned_url))) {
                        error = '-DEADLINK-'
                        log_text = log_text + error
                        print error
                        write_to_log(log_text)
                        return error
                    }
                    String temp_channel_stream_url_text = openURL( new URL(temp_returned_url), 
                        "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.83 Safari/537.1"
                        )
                    temp_channel_stream_url_text = temp_channel_stream_url_text.replaceAll('%3A',':')
                    temp_channel_stream_url_text = temp_channel_stream_url_text.replaceAll('%2F','/')
                    temp_channel_stream_url_text = temp_channel_stream_url_text.replaceAll('&amp;','&')                                         
                    temp_channel_stream_url_text = temp_channel_stream_url_text.replaceAll('&quot;','"')                                                         
                    temp_channel_stream_url_text = temp_channel_stream_url_text.replaceAll('%2D','-')
                    temp_channel_stream_url_text = temp_channel_stream_url_text.replaceAll('&lt;','<')                                         
                    temp_channel_stream_url_text = temp_channel_stream_url_text.replaceAll('&gt;','>')
                    
                    returned_url = '-NOTFOUND-'
                    
                    if (temp_channel_stream_url_text.contains('Embedding disabled for this Channel')) {                                   
                        
                        if (returned_url == '-NOTFOUND-') {
                            returned_url = process_for_PLAYPATH(
                                channel_stream_url_text,
                                '<iframe.*?src=".*?fcast\\.tv/watch\\.php\\?live=(.*?)".*?>',
                                (String[])[    
                                    'rtmp://37.221.166.70/live',
                                    'rtmp://37.221.166.69/live',
                                    'rtmp://109.163.236.66/live'
                                ],
                                'http://www.fcast.tv/embed.php?live=',
                                'http://www.fcast.tv/player/player-licensed.swf'
                            )
                        }
                        if (returned_url == '-NOTFOUND-') {
                            returned_url = process_for_PLAYPATH(
                                channel_stream_url_text,
                                "<script.*?fid='(.*?)';.*?src='.*?fcast\\.tv",
                                (String[])[    
                                    'rtmp://37.221.166.70/live',
                                    'rtmp://37.221.166.69/live',
                                    'rtmp://109.163.236.66/live'
                                ],
                                'http://www.fcast.tv/embed.php?live=',
                                'http://www.fcast.tv/player/player-licensed.swf'
                            )
                        }                                                        
                    }
                    else {
                        if (returned_url == '-NOTFOUND-' ) {
                            returned_url = process_for_SWF_PLAYPATH_STREAMER(
                                temp_channel_stream_url_text,
                                "(?s)<script.*?SWFObject\\('(.*?).php',.*?addVariable\\('file','(.*?)'\\);.*?addVariable\\('streamer','(.*?)'\\);",
                                current_url,
                                '.php'
                            )
                        }
                    }
                }
            }                       
            
            if (returned_url == '-NOTFOUND-') { 
                returned_url = process_for_URL(
                    channel_stream_url_text, 
                    '<pre>.*?cricfree.tv/update/(.*?)</pre>',
                    'http://cricfree.tv/update/'
                )                 
            }
            
            log_text = log_text + returned_url    
            log_text = log_text + ' '
            print returned_url + ' '
            
            if (returned_url == '-NOTFOUND-') {
                error = '-NOTFOUND-'
                write_to_log(log_text)
                return error
            }            
            else if (returned_url.contains("-URL-")) {
                returned_url = returned_url.replaceFirst("-URL-","")
                current_url = returned_url
                if (!URLExists(new URL(current_url))) {
                    error = '-DEADLINK-'
                    log_text = log_text + error
                    print error
                    write_to_log(log_text)
                    return error
                }
                channel_stream_url_text = openURL( new URL(current_url), 
                    "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.83 Safari/537.1"
                    )
//                channel_stream_url_text = channel_stream_url_text.replaceAll("\n","")
//                channel_stream_url_text = channel_stream_url_text.replaceAll("\r","")
                channel_stream_url_text = channel_stream_url_text.replaceAll('%3A',':')
                channel_stream_url_text = channel_stream_url_text.replaceAll('%2F','/')
                channel_stream_url_text = channel_stream_url_text.replaceAll('&amp;','&')                                         
                channel_stream_url_text = channel_stream_url_text.replaceAll('&quot;','"')                                                         
                channel_stream_url_text = channel_stream_url_text.replaceAll('%2D','-')
                channel_stream_url_text = channel_stream_url_text.replaceAll('&lt;','<')                                         
                channel_stream_url_text = channel_stream_url_text.replaceAll('&gt;','>')                                   
                
                /**                
                    println channel_stream_url_text
                    println ''
                    println ''                        
                    println ''
                    println ''
                    println ''                                                                                        
                /**/
            }
            else if (returned_url.contains("-STREAM-")) {
                rtmp_url = returned_url
                url_found = 1
            }         
        }             
        
        write_to_log(log_text)
        
        return rtmp_url   
    }
    
    WebResourceContainer extractItems(URL resourceURL, int maxItemsToRetrieve) {
    
        List<WebResourceItem> items = []
        
        if (URLExists(resourceURL) == false) {
            write_to_log("Invalid Resource URL")
            return null
        }        
        
        def resource_text = openURL(resourceURL,
            "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.83 Safari/537.1"
            )
        
        def channel_list_matcher = resource_text =~ CHANNEL_LIST_EXTRACTOR
        def channel_count = channel_list_matcher.count
        for (channel_number in 0..<channel_count) {
        //for (channel_number in 0..<10) {            
            def channel_url = channel_list_matcher[channel_number][1]
            
            if (channel_url.contains("index.php")) {
                continue;
            }
                        
            def channel_image = channel_list_matcher[channel_number][2]                                                
            
            def channel_title = channel_url
            channel_title = channel_title.replaceAll("/", "")
            channel_title = channel_title.replaceAll("live", "")
            channel_title = channel_title.replaceAll("sports-streaming", "")
            channel_title = channel_title.replaceAll("streaming", "")
            channel_title = channel_title.replaceAll("stream", "")
            channel_title = channel_title.replaceAll("tennis", "")
            channel_title = channel_title.replaceAll("football", "")
            channel_title = channel_title.replaceAll("rugby", "")
            channel_title = channel_title.replaceAll("golf", "")
            channel_title = channel_title.replaceAll("american", "")
            channel_title = channel_title.replaceAll("boxing", "")                        
            channel_title = channel_title.replaceAll("free", "")
            channel_title = channel_title.replaceAll(".php", "")
            channel_title = channel_title.replaceAll("-", "")
            
            def channel_cache_key = channel_title                        
            
            print channel_title
            //processChannel(BASE_URL + channel_url)
            println ''
            
            items << new WebResourceItem(title: channel_title, 
                additionalInfo: [channelURL: BASE_URL + channel_url, 
                    thumbnailURL: BASE_IMAGE_URL + channel_image, 
                    cacheKey: TITLE + '_' + channel_cache_key
                ]
            )
        }                
        
        return new WebResourceContainer(title: TITLE, items: items)
    }
    
    ContentURLContainer extractUrl(WebResourceItem item, PreferredQuality requestedQuality) {
    
        def rtmp_url = processChannel(item.additionalInfo.channelURL)
        if (rtmp_url.contains('-STREAM-')) {
            rtmp_url = rtmp_url.replaceFirst("-STREAM-", "")
        }
        else {
            return null
        }
                
        return new ContentURLContainer(contentUrl: rtmp_url, 
            thumbnailUrl: item.additionalInfo.thumbnailURL, 
            expiresImmediately: true, 
            cacheKey : item.additionalInfo.cacheKey,
            live: true
            )    
    }
    
    static void main(args) {
        
        CricFreeTV extractor = new CricFreeTV()
        
        WebResourceContainer container = extractor.extractItems( new URL("http://www.cricfree.tv/"), 5)
        /**/
        container.getItems().each {
            ContentURLContainer result = extractor.extractUrl(it, PreferredQuality.MEDIUM)
            println result
            println ''
        }
       /**/                  
    }
 }