#!/usr/bin/python
import sys
import os
import time
import ConfigParser
import tempfile
import codecs
from StringIO import StringIO
from util.xml import Xml

default_config = \
"""
"""

DEFAULT_CONFIG_FN = '/opt/planetstack/plstackapi_config'

def isbool(v):
	return v.lower() in ("true", "false")

def str2bool(v):
	return v.lower() in ("true", "1")

class Config:

	def __init__(self, config_file=None):
                if (config_file==None):
                    config_file = self.get_config_fn()

		self._files = []
		self.config_path = os.path.dirname(config_file)
		self.config = ConfigParser.ConfigParser()
		self.filename = config_file
		if not os.path.isfile(self.filename):
			self.create(self.filename)
		self.load(self.filename)

        def get_config_fn(self):
             # Look for "-C <something>" to get the
             # name of the config file. Using a real OptionParser here is
             # problematic as it will throw 'no such option' errors for options
             # that it does not understand.

             last = None
             for arg in sys.argv:
                 if (last=="-C"):
                     return arg
                 last = arg

             return DEFAULT_CONFIG_FN

	def _header(self):
		header = """
DO NOT EDIT. This file was automatically generated at
%s from:

%s
""" % (time.asctime(), os.linesep.join(self._files))

		# Get rid of the surrounding newlines
		return header.strip().split(os.linesep)

	def create(self, filename):
		if not os.path.exists(os.path.dirname(filename)):
			os.makedirs(os.path.dirname(filename))
		configfile = open(filename, 'w')
		configfile.write(default_config)
		configfile.close()


	def load(self, filename):
		if filename:
			try:
				self.config.read(filename)
			except ConfigParser.MissingSectionHeaderError:
				if filename.endswith('.xml'):
					self.load_xml(filename)
				else:
					self.load_shell(filename)
			self._files.append(filename)
			self.set_attributes()

	def load_xml(self, filename):
		xml = XML(filename)
		categories = xml.xpath('//configuration/variables/category')
		for category in categories:
			section_name = category.get('id')
			if not self.config.has_section(section_name):
				self.config.add_section(section_name)
			options = category.xpath('./variablelist/variable')
			for option in options:
				option_name = option.get('id')
				value = option.xpath('./value')[0].text
				if not value:
					value = ""
				self.config.set(section_name, option_name, value)

	def load_shell(self, filename):
		f = open(filename, 'r')
		for line in f:
			try:
				if line.startswith('#'):
					continue
				parts = line.strip().split("=")
				if len(parts) < 2:
					continue
				option = parts[0]
				value = parts[1].replace('"', '').replace("'","")
				section, var = self.locate_varname(option, strict=False)
				if section and var:
					self.set(section, var, value)
			except:
				pass
		f.close()

	def locate_varname(self, varname, strict=True):
		varname = varname.lower()
		sections = self.config.sections()
		section_name = ""
		var_name = ""
		for section in sections:
			if varname.startswith(section.lower()) and len(section) > len(section_name):
				section_name = section.lower()
				var_name = varname.replace(section_name, "")[1:]
		if strict and not self.config.has_option(section_name, var_name):
			raise ConfigParser.NoOptionError(var_name, section_name)
		return (section_name, var_name)

	def set_attributes(self):
		sections = self.config.sections()
		for section in sections:
			for item in self.config.items(section):
				name = "%s_%s" % (section, item[0])
				value = item[1]
				if isbool(value):
					value = str2bool(value)
				elif value.isdigit():
					value = int(value)
				setattr(self, name, value)
				setattr(self, name.upper(), value)


	def verify(self, config1, config2, validate_method):
		return True

	def validate_type(self, var_type, value):
		return True

	@staticmethod
	def is_xml(config_file):
		try:
			x = Xml(config_file)
			return True
		except:
			return False

	@staticmethod
	def is_ini(config_file):
		try:
			c = ConfigParser.ConfigParser()
			c.read(config_file)
			return True
		except ConfigParser.MissingSectionHeaderError:
			return False


	def dump(self, sections = []):
		sys.stdout.write(output_python())

	def output_python(self, encoding = "utf-8"):
		buf = codecs.lookup(encoding)[3](StringIO())
		buf.writelines(["# " + line + os.linesep for line in self._header()])

		for section in self.sections():
			buf.write("[%s]%s" % (section, os.linesep))
			for (name,value) in self.items(section):
				buf.write("%s=%s%s" % (name,value,os.linesep))
			buf.write(os.linesep)
		return buf.getvalue()

	def output_shell(self, show_comments = True, encoding = "utf-8"):
		"""
		Return variables as a shell script.
		"""

		buf = codecs.lookup(encoding)[3](StringIO())
		buf.writelines(["# " + line + os.linesep for line in self._header()])

		for section in self.sections():
			for (name,value) in self.items(section):
				# bash does not have the concept of NULL
				if value:
					option = "%s_%s" % (section.upper(), name.upper())
					if isbool(value):
						value = str(str2bool(value))
					elif not value.isdigit():
						value = '"%s"' % value
					buf.write(option + "=" + value + os.linesep)
		return buf.getvalue()

	def output_php(self, encoding = "utf-8"):
		"""
		Return variables as a PHP script.
		"""

		buf = codecs.lookup(encoding)[3](StringIO())
		buf.write("<?php" + os.linesep)
		buf.writelines(["// " + line + os.linesep for line in self._header()])

		for section in self.sections():
			for (name,value) in self.items(section):
				option = "%s_%s" % (section, name)
				buf.write(os.linesep)
				buf.write("// " + option + os.linesep)
				if value is None:
					value = 'NULL'
				buf.write("define('%s', %s);" % (option, value) + os.linesep)

		buf.write("?>" + os.linesep)

		return buf.getvalue()

	def output_xml(self, encoding = "utf-8"):
		pass

	def output_variables(self, encoding="utf-8"):
		"""
		Return list of all variable names.
		"""

		buf = codecs.lookup(encoding)[3](StringIO())
		for section in self.sections():
			for (name,value) in self.items(section):
				option = "%s_%s" % (section,name)
				buf.write(option + os.linesep)

		return buf.getvalue()
		pass

	def write(self, filename=None):
		if not filename:
			filename = self.filename
		configfile = open(filename, 'w')
		self.config.write(configfile)

	def save(self, filename=None):
		self.write(filename)

	def __getattr__(self, attr):
		return getattr(self.config, attr)

if __name__ == '__main__':
	filename = None
	if len(sys.argv) > 1:
		filename = sys.argv[1]
		config = Config(filename)
	else:
		config = Config()
	config.dump()
