import os
import urllib
import urllib2
import xml.dom.minidom

from twisted.internet import reactor
		
class SRCDSAutoUpdate:
	def __init__(self, state):
		self.state = state;
		self.debug = False;
		self.executeUpdateCheck();

	def steamAPICall(self, path, rawargs = {}):
		args = rawargs;
		args['format'] = 'xml';
		args = '?%s' % (urllib.urlencode(args));

		url = "%s/%s/%s" % ('https://api.steampowered.com', path, args);
		try:
			raw = urllib2.urlopen(url).read();
		except Exception:
			return False;

		try:
			dom = xml.dom.minidom.parseString(raw);
		except Exception:
			return False;

		response = dom.getElementsByTagName('response');
		if not len(response):
			return False;

		ret = {}
		for c in response[0].childNodes:
			if c.nodeType == xml.dom.minidom.Node.ELEMENT_NODE:
				if not len(c.childNodes):
					ret[c.nodeName] = "";
				elif c.childNodes[0].data.lower() == "true":
					ret[c.nodeName] = True;
				elif c.childNodes[0].data.lower() == "false":
					ret[c.nodeName] = False;
				else:
					ret[c.nodeName] = c.childNodes[0].data;
		return ret;

	def runCheck(self, appid, ver, autoupdate_key):
		call = self.steamAPICall('ISteamApps/UpToDateCheck/v0001', { 'appid': appid, 'version': ver });
		if (call == False or call['success'] != True):
			needs_update = False;
		elif (call['up_to_date'] == True):
			needs_update = False;
		else:
			needs_update = True;
		self.updateCheckCallback(autoupdate_key, needs_update);

	def executeUpdateCheck(self):
		config = self.state['config'];
		server_list = config.getServerList();
		self.autoupdate_dict = dict();

		for server_key in server_list:
			server = config.getServer(server_key);
			if('autoupdate' not in server or server['autoupdate'] != '1'):
				if(self.debug == True):
					print("Skipping %s, not marked for autoupdate"%(server_key));
				continue;
			gamename = None;
			version = None;
			appid = None;
			try:
				# open file
				inffile = open(os.path.join(server['dir'],"steam.inf"),"r");

				# read game directory, app id, and version
				for line in inffile:
					(key, value) = line.split("=");
					if(key == "PatchVersion"):
						version = value.strip();
					elif(key == "ProductName"):
						gamename = value.strip();
					elif(key == "appID"):
						appid = value.strip();
					elif(self.debug == True):
						print("server %s, Bad key: %s"%(server_key, key));
			except:
				if(self.debug == True):
					print("Error while reading steam.inf file");

			if(gamename == None or version == None or appid == None):
				if(self.debug == True):
					print("[aupdate %s]: Can't read steam.inf!"%(server_key));
				continue;
			# is appid unique?
			autoupdate_key = "%s/%s/%s"%(appid,gamename,version);
			if(autoupdate_key not in self.autoupdate_dict):
				reactor.callLater(1, lambda x_appid, x_version, x_autoupdate_key: self.runCheck(x_appid, x_version, x_autoupdate_key), appid, version, autoupdate_key);
				self.autoupdate_dict[autoupdate_key] = list();
			self.autoupdate_dict[autoupdate_key].append(server_key);
		reactor.callLater(60*10,self.executeUpdateCheck);

	def updateCheckCallback(self, autoupdate_key, needs_update):
		log = self.state['log'];
		router = self.state['router'];
		if(autoupdate_key in self.autoupdate_dict):
			if(needs_update == True):
				for server_key in self.autoupdate_dict[autoupdate_key]:
					server_status = self.state['servermgr'].server_status[server_key]['busy'];
					if (server_status == 2):
						continue;
					server = self.state['config'].getServer(server_key);
					self.state['ifcmgr'].interfaces['srcds_remote'].sendRemoteCommand(server_key, "sm_say [SCI] Game update has been detected, server will shut down soon for updates...");
					log.printToLog("[aupdate %s]: Master server says this instance is out of date.  Queuing for update..."%(server['name']))
					log.printToLog(router.routeLocalCommand("autoupdate %s"%(server_key)));
			elif(self.debug == True):
				print("Autoupdate timeout, assuming up to date.");
			del(self.autoupdate_dict[autoupdate_key]);