package com.ericsson.uecontrol.core.behaviour;

import android.media.MediaPlayer;

import com.ericsson.uecontrol.core.UeBehaviour;
import com.ericsson.uecontrol.gui.util.Configurator.Configurable;

import org.apache.log4j.Logger;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 * Created by ezivkoc on 2014-08-05.
 */
public class UeBehaviourVideoStreaming extends UeBehaviour implements MediaPlayer.OnErrorListener{
    private static final Logger log = Logger.getLogger(UeBehaviourVideoStreaming.class);
    protected static final String YOUTUBE_FEED_URL = "http://gdata.youtube.com/feeds/api/videos/";

    @Configurable("Streaming URL")
    private String url;

    private transient Exception playbackException;

    @Override
    protected void execute() throws Exception {
        MediaPlayer mp = new MediaPlayer();
        playbackException = null;
        mp.setOnErrorListener(this);

        try {
            String videoUrl = url.trim();
            if (isYouTubeUrl(videoUrl)) {
                videoUrl = getYoutubeRtsUrl(getYoutubeVideoId(videoUrl));
                log.debug("Detected youtube video link: " + videoUrl);
            }
            mp.setDataSource(videoUrl);
            mp.prepare();
            mp.start();

            Thread.sleep(UeBehaviourSleep.SLEEP_PERIOD);
            while (mp.isPlaying() && playbackException == null) {
                super.setProgress((float) mp.getCurrentPosition() / mp.getDuration());
                super.setHandledIncomingData(0); // Unable to retrieve the amount of incoming data
                if (super.stopExecution()) break;
                Thread.sleep(UeBehaviourSleep.SLEEP_PERIOD);
            }
        }catch(Exception e){
            throw e;
        }finally {
            mp.stop();
            mp.reset();
            mp.release();
        }
        if(playbackException != null)
            throw playbackException;
    }

    protected static boolean isYouTubeUrl(String url){
        return Pattern.matches("youtube\\.com.*v=", url) ||
                Pattern.matches("^[\\w-]*$", url);
    }
    protected static String getYoutubeVideoId(String url){
        if(Pattern.matches("^[\\w-]*$", url))
            return url;

        Pattern pattern = Pattern.compile("v=([\\w-]*)[&#]?");
        Matcher match = pattern.matcher(url);
        if(match.find())
            return match.group(1);
        return null;
    }
    protected String getYoutubeRtsUrl(String videoId) throws DocumentException, MalformedURLException {
        URL feedUrl = new URL(YOUTUBE_FEED_URL + videoId);
        Document document = new SAXReader().read(feedUrl);
        Attribute attr = (Attribute)document.selectSingleNode( "//media:content[@yt:format='6']/@url" );
        if(attr != null){
            return attr.getValue();
        }
        return null;
    }



    @Override
    public boolean onError(MediaPlayer mp, int what, int extra) {
        playbackException = new Exception(
                "Playback error: "+getErrorString(what)+", "+getErrorString(extra));
        return false;
    }
    private String getErrorString(int errorCode){
        switch(errorCode){
            case 0x00000001: return "MEDIA_ERROR_UNKNOWN";
            case 0x00000064: return "MEDIA_ERROR_SERVER_DIED";
            case 0x000000c8: return "MEDIA_ERROR_NOT_VALID_FOR_PROGRESSIVE_PLAYBACK";
            case 0xfffffc11: return "MEDIA_ERROR_MALFORMED";
            case 0xfffffc14: return "MEDIA_ERROR_IO";
            case 0xfffffc0e: return "MEDIA_ERROR_UNSUPPORTED";
            case 0xffffff92: return "MEDIA_ERROR_TIMED_OUT";
        }
        return "UNKNOWN_ERROR_CODE("+errorCode+")";
    }



    @Override
    public String getName() {
        return "Video Streaming";
    }

    @Override
    public String toString() {
        return "Will stream video from: "+url;
    }
}
