import groovy.util.Node
import groovy.xml.Namespace

import java.util.List

import org.restlet.*
import org.restlet.data.*
import org.serviio.library.metadata.*
import org.serviio.library.online.*

/**
 * penny-arcade.com content URL extractor plugin. 
 * 
 * @author Petr Nejedly
 *
 */
class PennyArcade extends FeedItemUrlExtractor {

	private static final httpClient = new Client(Protocol.HTTP);
	
    final VALID_FEED_URL = '^http(s)*://.*penny-arcade.com/feed/.*$'
	
    String getExtractorName() {
        return getClass().getName()
    }
    
    boolean extractorMatches(URL feedUrl) {
        return feedUrl ==~ VALID_FEED_URL
    }
    
    ContentURLContainer extractUrl(Map links, PreferredQuality requestedQuality) {
        def linkUrl = links.default
        def contentUrl
        
		// open the HTML page first		
		def webPage = linkUrl.getText()
		// find iframe content location 
		def matcher = webPage =~ '<iframe.*src=\\"(http.*/play.*\\.html)\"'
		def playerUrl = matcher[0][1]
		// get redirect URL
		
		Request request = new Request(Method.GET, playerUrl.toString());
		Response response = httpClient.handle(request);
		if (response.getStatus().isRedirection()) {
			// reirection URL includes ID of the video
			URL redirectionUrl = response.getLocationRef().toUrl()
			def feedUrlMatcher = URLDecoder.decode(redirectionUrl.toString(),'UTF-8') =~ '&file=(.+)&'
			def videoFeedUrl = feedUrlMatcher[0][1]
			// now make request for video details (feed)
			def videoFeedItemUrl = new URL(videoFeedUrl)
			// parse the feed item to get content URL			
			def rssNode = new XmlParser().parse( videoFeedItemUrl.toString() )
			def blipNs = new Namespace("http://blip.tv/dtd/blip/1.0")
			def itemNode = rssNode.channel.item[0]
			List contentNodes = itemNode.'media:group'.'media:content'.findAll { it -> it.attribute(blipNs.role).startsWith('Blip')}
			Node contentNode = findSuitableItem(contentNodes, requestedQuality, blipNs)
			
			contentUrl = contentNode.'@url'
			String thumbnailUrl = itemNode.'media:thumbnail'.'@url'.text()
			return new ContentURLContainer(contentUrl: contentUrl, thumbnailUrl: thumbnailUrl)
		}
		log('Blip.tv redirect did not happen, somehting went wrong or the API changed')
        return null
    }
     
	
	def Node findSuitableItem(List contentNodes, PreferredQuality requestedQuality, Namespace blipNs) {
		Node result
		if(requestedQuality == PreferredQuality.LOW) {
			result = contentNodes.find { it -> it.attribute(blipNs.role) == 'Blip LD' }
		} else if (requestedQuality == PreferredQuality.MEDIUM) {
			result = contentNodes.find { it -> it.attribute(blipNs.role) == 'Blip SD' }
		} else {
			result = contentNodes.find { it -> it.attribute(blipNs.role).startsWith('Blip HD') }
		}
		if( result == null ) {
			// nothing found, get the first
			return contentNodes.head()
		}
		return result
	}
	
    static void main(args) {
		// this is just to test
        PennyArcade extractor = new PennyArcade()
		
		assert extractor.extractorMatches( new URL("http://penny-arcade.com/feed/show") )
		assert !extractor.extractorMatches( new URL("http://google.com/feeds/api/standardfeeds/top_rated?time=today") )
		
		Map links = ['default': new URL('http://penny-arcade.com/patv/episode/sony-knows-it-has-a-problem')]
		
        ContentURLContainer result = extractor.extractUrl(links, PreferredQuality.MEDIUM)
        println "Result: $result"
    }
}