import org.serviio.library.online.WebResourceUrlExtractor
import org.serviio.library.online.ContentURLContainer
import org.serviio.library.online.WebResourceItem
import org.serviio.library.online.PreferredQuality
import org.serviio.library.online.WebResourceContainer
import groovy.json.JsonSlurper
import org.serviio.library.metadata.MediaFileType
import org.restlet.data.Method
import org.restlet.Request
import org.restlet.Client
import org.restlet.data.Protocol
import org.restlet.Response
import org.restlet.data.Status
import org.restlet.data.ClientInfo
import sun.misc.BASE64Decoder

/**
 * WebResource extractor plugin for forum.stepashka.com
 *
 * @author Michael Mishalov
 * @version 1.4.1
 */
class Stepashka extends WebResourceUrlExtractor {
    final static VALID_WEB_RESOURCE_URL                     = '^(?:http?://)?(?:www\\.)?(forum.|online.)?stepashka.com/.*'
    final static WEB_RESOURCE_TITLE                         = /(?s)<h1 class=\"btl\">(.*?)<\/h1>/
    final static FILE_RESOURCE                              = /((?s)&amp;file=(.*?)&uid=)|((?s)&file=(.*?)")/
    final static PLAY_LIST_RESOURCE                         = /(?s)(&amp;|&)pl=(.*?)"/
    final static CHARSET_META                               = /(?s)charset=(.*?)"/
    final static USER_AGENT                                 = 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.186 Safari/535.1'
    final static DEFAULT_THUMBNAIL_URL                      = "http://antoinebustros.com/blog/wp-content/uploads/2007/04/neg-film.jpg"
    final static codecA =  ["G", "d", "R", "0", "M", "Y", "4", "v", "6", "u", "t", "i", "f", "c", "s", "l", "B", "5", "n", "2", "V", "Z", "J", "m", "L", "="];
    final static codecB =  ["1", "w", "Q", "o", "9", "U", "a", "N", "x", "D", "X", "7", "z", "H", "y", "3", "e", "g", "T", "W", "b", "8", "k", "I", "p", "r"];


    @Override
    protected WebResourceContainer extractItems(URL url, int i) {
        String pageSource = openURL(url);
        String charset = ((pageSource=~CHARSET_META)[0]-null)[-1].toString().trim()
        String webResourceTitle =(((pageSource =~ WEB_RESOURCE_TITLE)[0]-null)[-1]).trim()
        if(!charset.equalsIgnoreCase("Windows-1251")){
            webResourceTitle = webResourceTitle.replaceAll("с","c")
            webResourceTitle = webResourceTitle.replaceAll("С","C")
            webResourceTitle = new String(webResourceTitle.getBytes(),"UTF-8")
        }
        def videoResources = pageSource =~ FILE_RESOURCE
        List<WebResourceItem> items = []
        if (videoResources.size() > 0){
            items << new WebResourceItem(title: webResourceTitle, additionalInfo: ['link' :decrypt(((String)(videoResources[0]-null)[-1]).trim())])
        }else{
            videoResources = pageSource =~ PLAY_LIST_RESOURCE
            assert videoResources.size() > 0
            def slurper = new JsonSlurper()
            String encodedPL = openURL(new URL(decrypt(videoResources[0][-1].toString().trim())), USER_AGENT).trim();
            String json = decrypt(encodedPL);
            if(!json.startsWith("{")){
                int index = json.indexOf("{");
                assert index > 0
                json = json.substring(index);
            }
            def playlist = slurper.parseText(json)
            items.addAll(fetchItems(playlist))
        }
        return new WebResourceContainer(title: webResourceTitle, thumbnailUrl: DEFAULT_THUMBNAIL_URL, items: items)
    }
    private String openURL(URL url){
        Request request = new Request(Method.GET, url.toString());
        Client client = new Client(Protocol.HTTP);
        ClientInfo info = new ClientInfo();
        info.setAgent(USER_AGENT);
        request.setClientInfo(info);
        Response response = client.handle(request);
        String orPageSource
        if(Status.SUCCESS_OK.equals(response.getStatus())){
            return response.getEntityAsText()
        }
        return ""
    }
    /**
     * Finds all actual video links and titles in received data
     * @param data to search
     * @return List contains all founded items
     */
    private List<WebResourceItem> fetchItems(data){
        List<WebResourceItem> items = [];
        if(data in HashMap){
            def playlist = data.playlist 
            if(playlist){
               items.addAll(fetchItems(playlist))
            }else{
                String link = data.file;
                String title = data.comment;
                items << new WebResourceItem(title: title, additionalInfo: ['link' :link])
            }
        }else if (data in ArrayList){
            data.each{
                items.addAll(fetchItems(it))
            }
        }
        return items;
    }
    @Override
    protected ContentURLContainer extractUrl(WebResourceItem webResourceItem, PreferredQuality preferredQuality) {
        log("Extracting:"+ webResourceItem.additionalInfo.link)
        return new ContentURLContainer(fileType: MediaFileType.VIDEO, contentUrl: webResourceItem.additionalInfo.link)
    }
    private String decrypt(String input) {
        String output = input;
        for(int i = 0; i<codecA.size();i++){
            output = swap(codecB[i],codecA[i],output);
        }
        BASE64Decoder decoder = new BASE64Decoder();
        output = new String(decoder.decodeBuffer(output),"UTF8");
        return output;
    }
    private String swap(String first, String second, String input) {
        String output = input.replace(first, "___");
        output = output.replace(second, first);
        output = output.replace("___", second);
        return output;
    }

    @Override
    boolean extractorMatches(URL url) {
        return url ==~ VALID_WEB_RESOURCE_URL
    }

    @Override
    String getExtractorName() {
        return getClass().getName()
    }

    static void main(args) {
        //def TestUrl = new URL("http://online.stepashka.com/eng-serialy/3350-spartak-bogi-areny-spartacus-gods-of-the-arena-2011.html")
        //def TestUrl = new URL("http://forum.stepashka.com/t564467/")
        def TestUrl = new URL("http://online.stepashka.com/serialy/eng-serialy/3390-gran-za-granyu-fringe-2008-2012.html")
        //def TestUrl = new URL("http://online.stepashka.com/serialy/eng-serialy/3212-igra-prestolov-game-of-thrones-2011.html")
        //def TestUrl = new URL("http://online.stepashka.com/serialy/eng-serialy/17216-strela-arrow-serial-2012.html")
        Stepashka extractor = new Stepashka()
        println "PluginName               : " + extractor.getExtractorName();
        println "TestMatch                : " + extractor.extractorMatches(TestUrl);
        WebResourceContainer container = extractor.extractItems(TestUrl, -1);
        container.getItems().each {
            println "URL                  : " + extractor.extractUrl(it, PreferredQuality.HIGH)
        }

    }
}
