import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;

import org.serviio.library.metadata.*
import org.serviio.library.online.*

import groovyx.net.http.*
import static groovyx.net.http.ContentType.*

class NHLGameCenterPlugin extends WebResourceUrlExtractor
{	
	static final USERNAME = 'XXXXXXXX';
	static final PASSWORD = 'XXXXXXXX';
	
	
	final VALID_FEED_URL = '^http://www.nhl.com/ice/gamecenterlive.htm.*$';
	
	final String EXTRACTOR_NAME = 'NHL Gamecenter Live';
	
	final String NHL_LOGO = 'http://cdn.nhl.com/images/default/nhl_shield.png';
	
	final String THUMB_URL_A = 'http://1.cdn.nhle.com/';
	final String THUMB_URL_B = '/images/logos/large.png';
		
	final String PLACEHOLDER_CONTENT_URL = 'http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8';
	
	final TimeZone EASTERN_TIMEZONE = TimeZone.getTimeZone('America/New_York')	
	
	String ivAuthToken = null;
	
	boolean extractorMatches(URL fvURL) 
	{
		return fvURL ==~ VALID_FEED_URL;
	}
	
	String getExtractorName()	
	{
		return EXTRACTOR_NAME;
	}
	
	void Authenticate(String fvUser, String fvPassword)
	{
		if(ivAuthToken != null)
		{
			//already authenticated
			return;
		}
		
		String tvAuthUrl = 'https://gamecenter.nhl.com';
		
		def tvHttp = new HTTPBuilder(tvAuthUrl);
		
		tvHttp.post(path: '/nhlgc/secure/login',
					query: [username: fvUser, password: fvPassword])
		{ fvResponse, fvXml ->
			if(!fvXml.code.text().equals('loginsuccess'))
			{				
				return;
			}
			
			if(!fvXml.data.gclSubscription.text().equals('true'))
			{
				return;
			}
			
			if(!fvXml.data.hasSubscription.text().equals('true'))
			{
				return;
			}					
			
			fvResponse.headers.each 
			{ fvHeader ->
				if(!fvHeader.name.equals('Set-Cookie'))
				{
					return;
				}
				
				if(!fvHeader.value.startsWith('rfclient_auth='))
				{
					return;
				}
				
				ivAuthToken = fvHeader.value.substring(0, fvHeader.value.indexOf('; '));
			}
		}
		
		if(ivAuthToken == null)
		{
			log("Auth failed");			
		}
	}
	
	WebResourceContainer extractItems(URL fvURL, int fvNumItems) 
	{	
		Authenticate(USERNAME, PASSWORD);	
		if(ivAuthToken == null)
		{
			return null;
		}
		
		String tvReqUrl = 'http://feeds.cdnak.neulion.com';
		
		def tvHttp = new HTTPBuilder(tvReqUrl);		
		
		List<WebResourceItem> tvWebItemList = new ArrayList<WebResourceItem>();
		
		//arbitrary - if it is before 5am EST time today, get yesterday's games
		GregorianCalendar tvCal = new GregorianCalendar(EASTERN_TIMEZONE);
		if(tvCal.get(Calendar.HOUR_OF_DAY) < 5)
		{
			tvCal.add(Calendar.DAY_OF_MONTH, -1);
		}
		
		String tvDateStr = tvCal.getTime().format('yyyyMMdd');
		
		tvHttp.get(path: '/fs/nhl/mobile/feeds/data/' + tvDateStr + '.xml',
				   headers: [Cookie: ivAuthToken])
		{ fvResponse, fvXml ->
			fvXml.game.each
			{ fvNode ->			
				
				if(!(fvNode.'game-state'.text().length() == 0 || fvNode.'game-state'.equals("LIVE")))
				{
					return;
				}
				
				String tvGID = fvNode.'game-number'.text();
				for(int i = tvGID.length(); i < 4; i++)
				{
					tvGID = "0" + tvGID;
				}
				
				String tvSeason = fvNode.season.text().substring(0, 4);
				
				Boolean tvGame = true;
				def tvGameHttp = new HTTPBuilder('http://gamecenter.nhl.com');
				
				tvGameHttp.post(path: '/nhlgc/servlets/game',
								contentType: TEXT,								
								headers: [Cookie: ivAuthToken, Accept: 'application/xml'],
								query: [type: '2', isFlex: 'true', gid: tvGID, season: tvSeason])
				{ fvGResponse, fvTxt ->
					fvTxt.text.eachLine 
					{ fvLine ->
						if(fvLine ==~ 'blocked.+true')
						{
							tvGame = false;
						}
					}
				}
				
				if(!tvGame)
				{
					return;
				}
					
				SimpleDateFormat tvFmt = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
				tvFmt.setTimeZone(EASTERN_TIMEZONE);
				Date tvGameDate = tvFmt.parse(fvNode.'eastern-start-time'.text());
				
				DecimalFormat tvDecFmt = new DecimalFormat('00');								
				
				String tvTitle = '[' + tvDecFmt.format(tvGameDate.getHours()) + ":" + tvDecFmt.format(tvGameDate.getMinutes()) + '] ' +
								 fvNode.'away-team'.'city'.text() + " " +
							     fvNode.'away-team'.'name'.text() +
								 " @ " +
								 fvNode.'home-team'.'city'.text() + " " +
								 fvNode.'home-team'.'name'.text();
				
				Map<String, String> tvInfo = new HashMap<String, String>();
				tvInfo.put("ID", fvNode.'game-number');
				tvInfo.put("TEAM", "HOME");				
				WebResourceItem tvHomeItem = new WebResourceItem(title: tvTitle + " [HOME]", releaseDate: tvGameDate, additionalInfo: tvInfo);
				tvWebItemList.add(tvHomeItem);
				
				tvInfo = new HashMap<String, String>();
				tvInfo.put("ID", fvNode.'game-number');
				tvInfo.put("TEAM", "AWAY");
				WebResourceItem tvAwayItem = new WebResourceItem(title: tvTitle + " [AWAY]", releaseDate: tvGameDate, additionalInfo: tvInfo);
				tvWebItemList.add(tvAwayItem);
								
			}
		}
		
		WebResourceContainer tvReturn = new WebResourceContainer(title: "NHL Gamecenter Live", thumbnailUrl: NHL_LOGO, items: tvWebItemList);		
		
		return tvReturn;
	}
	
	ContentURLContainer extractUrl(WebResourceItem fvItem, PreferredQuality fvQuality) 
	{
		Authenticate(USERNAME, PASSWORD);
		if(ivAuthToken == null)
		{
			return null;
		}
		
		//arbitrary - if it is before 5am EST time today, get yesterday's games
		GregorianCalendar tvCal = new GregorianCalendar(EASTERN_TIMEZONE);
		if(tvCal.get(Calendar.HOUR_OF_DAY) < 5)
		{
			tvCal.add(Calendar.DAY_OF_MONTH, -1);
		}
		
		String tvDateStr = tvCal.getTime().format("yyyyMMdd");
		
		String tvReqUrl = "http://feeds.cdnak.neulion.com";		
		
		String tvContentUrl = null;
		String tvThumbUrl = null;
		
		def tvHttp = new HTTPBuilder(tvReqUrl);
		tvHttp.get(path: '/fs/nhl/mobile/feeds/data/' + tvDateStr + ".xml",
				   headers: [Cookie: ivAuthToken])
		{ fvResponse, fvXml ->
			def tvGame = fvXml.game.find{ it.'game-number' == fvItem.getAdditionalInfo()["ID"] };						
			
			if(fvItem.getAdditionalInfo()["TEAM"].equals("HOME"))
			{
				tvContentUrl = tvGame.streams.'sony_ced'.home.live.text();
				tvThumbUrl = THUMB_URL_A + tvGame.'home-team'.'name'.text().replace(' ', '').toLowerCase() + THUMB_URL_B;					            
			}
			else
			{
				tvContentUrl = tvGame.streams.'sony_ced'.away.live.text();
				tvThumbUrl = THUMB_URL_A + tvGame.'away-team'.'name'.text().replace(' ', '').toLowerCase() + THUMB_URL_B;
			}	
		}
		
		Boolean tvExpires = true;
		if(tvContentUrl != null && !tvContentUrl.isEmpty())
		{
			tvExpires = false;
		}
		else
		{
			tvContentUrl = PLACEHOLDER_CONTENT_URL;
		}
		
		ContentURLContainer tvReturn = new ContentURLContainer(	expiresImmediately: tvExpires, 
															 	live: !tvExpires, 
																fileType: MediaFileType.VIDEO, 
																thumbnailUrl: tvThumbUrl,
																contentUrl: tvContentUrl );
		
		String tvCacheKey = fvItem.getAdditionalInfo()["ID"].toString();
		if(fvItem.getAdditionalInfo()["TEAM"].equals("HOME"))
		{
			tvCacheKey += "0";
		}
		else
		{
			tvCacheKey += "1";
		}
																														
        tvReturn.setCacheKey(tvCacheKey);
		
		//force expiry 8 hours after start time
		if(!tvExpires)
		{
			GregorianCalendar tvExpCal = new GregorianCalendar(EASTERN_TIMEZONE);
			tvExpCal.setTime(fvItem.getReleaseDate());
			tvExpCal.add(Calendar.HOUR_OF_DAY, 8);
			
			tvReturn.setExpiresOn(tvExpCal.getTime());			
		}
															
		return tvReturn;
	}	
		
	static void main(args)
	{
		NHLGameCenterPlugin tvPlugin = new NHLGameCenterPlugin();
		
		println tvPlugin.extractorMatches(new URL('http://www.nhl.com/ice/gamecenterlive.htm'));
		
		println tvPlugin.Authenticate(USERNAME, PASSWORD);
		
		WebResourceContainer tvContainer = tvPlugin.extractItems(new URL('http://www.nhl.com/ice/gamecenterlive.htm'), -1);
		tvContainer.getItems().each { println(it); println tvPlugin.extractUrl(it, PreferredQuality.HIGH); println ""; };
	}
}
