import io, os, re, fnmatch
import sys, gtk
import codecs, ConfigParser
from time import localtime, strftime
from subprocess import Popen, PIPE, STDOUT, call
TUNED_CONF="""[sysctl]\n"""

class Config:
	#init config, load /etc/tuna.conf (if not exist, create it)
	def __init__(self):
		self.aliasList = []
		self.aliasReverse = []
		self.configFile = "/etc/tuna.conf"

		try:
			self.configParser = ConfigParser.RawConfigParser()
			self.configParser.read(self.configFile)
			cfg = self.configParser.items('global')
		except ConfigParser.Error:
			f = open(self.configFile,'w')
			f.write("[global]\n")
			f.write("root=/etc/tuna/\n")
			f.write("lastFile=\n")
			f.close()
			self.configParser.read(self.configFile)
			cfg = self.configParser.items('global')
		self.config = {}

		for option, value in cfg:
			self.config[option] = value
		self.cacheFileName = ''

	def FileNameToConfigPath(self, filename):
		return filename.replace(".", "\\.").replace("/", ".")

	def ConfigPathToFileName(self, configpath):
		return configpath.replace(".", "/").replace("\\/", ".")

	def updateDefault(self, filename):
		if filename.replace("", "temp-direct-load.conf") != filename:
			self.temp = ConfigParser.RawConfigParser()
			self.temp.read(self.configFile)
			self.temp.set('global', 'lastFile', filename)
			with open(self.configFile, 'wb') as cfgfile:
				self.temp.write(cfgfile)
			self.config['lastfile'] = filename

	def load(self, profileName):
		tmp = ConfigParser.RawConfigParser()
		tmp.read(self.config['root'] + profileName)
		try:
			check = tmp.items('categories')
		except ConfigParser.NoSectionError:
			if(self.tuned2Tuna(profileName) < 0):
				return -1
		return self.loadTuna(profileName)

	def tuned2Tuna(self,profileName):
		try:
			tmp = ConfigParser.RawConfigParser()
			tmp.read(self.config['root']+profileName)
			content = tmp.items('sysctl')
			f = open(self.config['root']+profileName,'w')
			f.write("[categories]\n")
			f.write("sysctl=Tuned import\n")
			f.write("[sysctl]\n")
			for option,value in content:
				f.write(option + "=" + value + "\n")
			f.close()
			return 0
		except (ConfigParser.Error, IOError):
			dialog = gtk.MessageDialog(None, 0, gtk.MESSAGE_ERROR,\
			 gtk.BUTTONS_OK, "%s\n%s" % \
			 (_("Corruputed config file: "), _(self.config['root']+profileName)))
			ret = dialog.run()
			dialog.destroy()
			return -1

	def checkTunedDaemon(self):
		for path in os.environ["PATH"].split(os.pathsep):
			path = path.strip('"')
			tFile = os.path.join(path, "tuned")
			if os.path.isfile(tFile) and os.access(tFile, os.X_OK):
				return True
		return False

	def currentActiveProfile(self):
		proc = Popen(["tuned-adm", "active"], stdout=PIPE, stderr=PIPE)
		ret = proc.communicate()
		profile = ret[0]
		if profile and profile.find("Current active profile: ") == 0:
			return (profile[len("Current active profile: "):profile.find("\n")],ret[1])
		return ("unknown",ret[1])

	def setCurrentActiveProfile(self):
		call("tuned-adm profile tuna", shell=True)

	def saveTuned(self, data):
		ldir = "/etc/tuned/tuna"
		profile = self.currentActiveProfile()
		if profile[1]:
			raise RuntimeError (_("Can't activate tuna profile in tuned daemon\n%s" % profile[1]))
			return False
		if not os.path.exists(ldir):
			try:
				os.stat(ldir)
			except (IOError,OSError):
				os.mkdir(ldir)
		f = codecs.open(os.path.join(ldir, "tuned.conf"), "w", "utf-8")
		f.write(TUNED_CONF)
		for index in data:
			for ind in data[index]:
				f.write(self.aliasToOriginal(data[index][ind]["label"])+"="+data[index][ind]["value"]+"\n")
		f.close()
		if profile[0] != "tuna":
			dialog = gtk.MessageDialog(None,gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
						gtk.MESSAGE_WARNING, gtk.BUTTONS_YES_NO, "%s%s\n%s" % \
						(_("Current active profile is: "),
						_(profile[0]),
						_("Set new created profile as current in tuned daemon?")))
			ret = dialog.run()
			dialog.destroy()
			if ret == gtk.RESPONSE_YES:
				self.setCurrentActiveProfile()
				if self.currentActiveProfile()[0] != "tuna":
					raise RuntimeError ("%s %s\n%s" % \
						(_("Current active profile is: "),
						_(profile),
						_("Setting of new tuned profile failed! Check if tuned is installed and active")))
					return False
				else:
					dialog = gtk.MessageDialog(None,gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
						gtk.MESSAGE_INFO, gtk.BUTTONS_OK, _("Tuna profile is now active in tuned daemon."))
					ret = dialog.run()
					dialog.destroy()
		return True


	def loadTuna(self, profileName):
		err = self.checkConfigFile(self.config['root'] + profileName)
		if err != '':
			raise RuntimeError(_("Config file contain errors: ") + _(err))
			return -1
		try:
			self.configParser = ConfigParser.RawConfigParser()
			self.configParser.read(self.config['root'] + profileName)
			tempCategories = self.configParser.items('categories')
			self.catIndex = 0
			self.categoriesOrigin = {}
			self.categories = {}
			self.ctlParams = {}
			self.ctlGuiParams = {}
			self.aliasList = []
			self.aliasReverse = []
			for option, value in tempCategories:
				if value != "":
					oldTempCfg = self.configParser.items(option)
					self.ctlParams[self.catIndex] = {}
					self.ctlGuiParams[self.catIndex] = {}
					tempCfg = []
					for index in range(len(oldTempCfg)):
						if self.isFnString(oldTempCfg[index][0]):
							expanded = self.getFilesByFN("/proc/sys", self.ConfigPathToFileName(oldTempCfg[index][0]))
							for index2 in range(len(expanded)):
								expandedData = (self.FileNameToConfigPath(expanded[index2]), oldTempCfg[index][1])
								tempCfg.append(expandedData)
						else:
							tempCfg.append(oldTempCfg[index])
					for opt, val in tempCfg:
						if val.find(',') != -1 and val.find(',',val.find(',')) != -1 and len(val.split(",")) > 2:
							self.ctlGuiParams[self.catIndex][opt] = val.split(",")
							val = self.ctlGuiParams[self.catIndex][opt][2]
						sys = self.getSystemValue(opt)
						if val == "" or val == sys:
							self.ctlParams[self.catIndex][opt] = sys
						else:
							self.ctlParams[self.catIndex][opt] = val
						if opt in self.ctlGuiParams[self.catIndex]:
							if self.ctlGuiParams[self.catIndex][opt][0] == '':
								self.ctlGuiParams[self.catIndex][opt][0] = int(int(self.ctlParams[self.catIndex][opt])/10)
							else:
								self.ctlGuiParams[self.catIndex][opt][0] = int(self.ctlGuiParams[self.catIndex][opt][0])
							if self.ctlGuiParams[self.catIndex][opt][1] == '':
								self.ctlGuiParams[self.catIndex][opt][1] = int(int(self.ctlParams[self.catIndex][opt])*10)
							else:
								self.ctlGuiParams[self.catIndex][opt][1] = int(self.ctlGuiParams[self.catIndex][opt][1])
					self.categories[self.catIndex] = value
					self.categoriesOrigin[self.catIndex] = option
					self.catIndex = self.catIndex + 1
		except (ConfigParser.Error, IOError):
			print _("Config file is corrupted")
			return -1
		try:
			self.aliasList = self.configParser.items('guiAlias')
		except ConfigParser.Error:
			self.aliasList = []
		self.aliasReverse = []
		return 0

	def updateDescription(self, filename):
		try:
			self.temp = ConfigParser.RawConfigParser()
			self.temp.read(self.config['root'] + filename)
			self.description = self.temp.items('fileDescription')
			self.description = dict(self.description)['text']
		except ConfigParser.Error as e:
			self.description = _("Description for this profile not found")
			if e != ConfigParser.NoSectionError:
				print e
		return self.description

	def fileToCache(self, profileName):
		try:
			f = open(self.config['root'] + profileName, 'r')
		except IOError:
			pass
		if f is None:
			raise RuntimeError(_("Cant open this config file: %s" % (self.config['root'] + profileName)))
			return False
		self.cacheFileName = profileName
		self.cache = f.read()
		f.close()
		self.updateDescription(profileName)

	def cacheToFile(self, profileName):
		try:
			f = open(self.config['root'] + profileName, 'w')
			f.write(self.cache)
			f.close()
		except IOError:
			print _("Cant write to config file: %s" % (self.config['root'] + profileName))

	def loadDirect(self, data):
		try:
			f = open(self.config['root']+"temp-direct-load.conf", 'w')
		except IOError:
			raise RuntimeError(_("Cant open this config file: %stemp-direct-load.conf" % (self.config['root'])))
		f.write(data)
		f.close()
		ret = self.load("temp-direct-load.conf")
		os.unlink(self.config['root']+"temp-direct-load.conf")
		return ret

	def populate(self):
		return [files for files in os.listdir(self.config['root']) if files!="temp-direct-load.conf"]
	
	def getSystemValue(self, filename):
		filename = self.aliasToOriginal(filename)
		try:
			buffer = open("/proc/sys/" + self.ConfigPathToFileName(filename), 'r').read()
		except IOError:
			print _("Invalid item! file: /proc/sys/%s" %(self.ConfigPathToFileName(filename)))
			return ""
		return buffer.strip()

	def setSystemValue(self, filename, value):
		filename = self.aliasToOriginal(filename)
		old = self.getSystemValue(filename)
		if value == "" or old == value:
			return 0
		try:
			fp = open("/proc/sys/" + self.ConfigPathToFileName(filename), 'w')
			fp.write(value)
		except IOError:
			print "%s%s %s %s" % (_("Cant write to file! path: /proc/sys/"), self.ConfigPathToFileName(filename), _("value:"), value)
			return -1
		return 0

	def applyChanges(self, data):
		for cat in data:
			for itemId in data[cat]:
				self.setSystemValue(data[cat][itemId]['label'], data[cat][itemId]['value'])
		self.reloadSystemValues(data)

	def reloadSystemValues(self, data):
		for cat in self.ctlParams:
			for param in self.ctlParams[cat]:
				sys = self.getSystemValue(param)
				self.ctlParams[cat][param] = sys

	def aliasToOriginal(self, string):
		string = string.replace("*","")
		if string in dict(self.aliasReverse):
			return dict(self.aliasReverse)[string]
		return string

	def originalToAlias(self, string):
		tmpString = string
		for src,dst in self.aliasList:
			tmpString = tmpString.replace(src,dst)
			if string != tmpString:
				self.aliasReverse[len(self.aliasReverse):] = [(tmpString,string)]
				return tmpString
		return string

	def saveSnapshot(self,data):
		tempconfig = ConfigParser.RawConfigParser()
		tempconfig.readfp(io.BytesIO(self.cache))
		snapcat = tempconfig.items('categories')
		out = {}
		cats = {}
		for opt,val in snapcat:
			for index in range(len(data[val])):
				data[val][index]['label'] = self.aliasToOriginal(data[val][index]['label'])
				out[data[val][index]['label']] = data[val][index]['value']
		for opt,val in snapcat:
			snapcontPacked = tempconfig.items(opt)
			snapcont = []
			for index in range(len(snapcontPacked)):
				if self.isFnString(snapcontPacked[index][0]):
					expanded = self.getFilesByFN("/proc/sys",self.ConfigPathToFileName(snapcontPacked[index][0]))
					for index2 in range(len(expanded)):
						expandedData = (self.FileNameToConfigPath(expanded[index2]),snapcontPacked[index][1])
						snapcont.append(expandedData)
				else:
					snapcont.append(snapcontPacked[index])
			for iopt,ival in snapcont:
				if ival == '':
					tempconfig.set(opt, iopt, out[iopt])
				elif ival == ',,':
					tempconfig.set(opt, iopt, ',,' + out[iopt])
				else:
					reival = ival
					pos = [reival.start() for reival in re.finditer(',', reival)]
					if len(pos) == 2:
						ival = ival[0:pos[1]+1]
						tempconfig.set(opt, iopt, ival + out[iopt])
					else:
						tempconfig.set(opt, iopt, out[iopt])
		if 'lastfile' in self.config:
			self.name = self.config['lastfile'].replace('.conf', '')
		else:
			self.name = 'snapshot'
		snapFileName = self.config['root'] + self.name + strftime("-%Y-%m-%d-%H:%M:%S", localtime()) + '.conf'
		try:
			with open(snapFileName , 'w') as configfile:
				tempconfig.write(configfile)
		except IOError:
			print _("Cant save snapshot")
		return snapFileName

	def checkConfigFile(self, filename):
		self.empty = True
		try:
			msgStack = ''
			if not os.path.exists(filename):
				msgStack = "%s%s %s %s" % (msgStack, _("Error: File"), filename, _("not found\n"))
				return msgStack
			self.checkParser = ConfigParser.RawConfigParser()
			self.checkParser.read(filename)
			for option,value in self.checkParser.items('categories'):
				if not self.checkParser.items(option):
					msgStack = "%s%s %s\n" % (msgStack, _("Error: Enabled section is empty:"), option)
					return msgStack
				current = self.checkParser.items(option)
				for opt,val in current:
					if not os.path.exists("/proc/sys/" + self.ConfigPathToFileName(opt)) and len(self.getFilesByFN("/proc/sys/", self.ConfigPathToFileName(opt))) == 0:
						msgStack = "%s%s%s\n" % (msgStack, _("Warning: File not found: /proc/sys/"), opt)
					self.empty = False
			if self.empty:
				msgStack = "%s%s" % (msgStack, _("Empty config File"))
			return msgStack
		except (ConfigParser.Error, IOError) as e:
			return "Error {0}".format(str(e))

	def fixConfigFile(self, filename):
		try:
			self.checkParser = ConfigParser.RawConfigParser()
			self.checkParser.read(filename)
			for option,value in self.checkParser.items('categories'):
				if not self.checkParser.items(option):
					self.checkParser.remove_option('categories', option)
					self.checkParser.set('categories', '#' + option, value)
				current = self.checkParser.items(option)
				for opt,val in current:
					if not os.path.exists("/proc/sys/" + self.ConfigPathToFileName(opt)) and len(self.getFilesByFN("/proc/sys/", self.ConfigPathToFileName(opt))) == 0:
						self.checkParser.remove_option(option, opt)
						self.checkParser.set(option, '#' + opt, val)
		except (ConfigParser.Error, IOError) as e:
			return "Error {0}".format(str(e))
		with open(filename, 'w') as configfile:
			self.checkParser.write(configfile)

	def isFnString(self, string):
		regMatch = ['[', '*', '?']
		for char in regMatch:
			if char in string:
				return True
		return False

	def getFilesByFN(self, troot, fn):
		mylist = {}
		for root, dirs, files in os.walk(troot, topdown=True):
			for cfile in files:
				if fnmatch.fnmatch(root + "/" + cfile, "*" + fn):
					mylist[len(mylist)] = root.replace(troot,"")[1:] + "/" + cfile
		return mylist
