#!/usr/bin/python3
#-*- coding: utf-8 -*-
##############################################
# Home	: http://netkiller.github.io
# Author: Neo <netkiller@msn.com>
##############################################

try:
	import time
	import os, sys
	import socket
	import logging, logging.handlers
	import socketserver
	import configparser
	from optparse import OptionParser, OptionGroup
except ImportError as err:
	print("Error: %s" %(err))

try:
	basedir=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
	sys.path.append(basedir + '/lib/python3.4/site-packages')
	sys.path.append(basedir + '/library')
	from rsync import *
	from git import *

	from datetime import datetime
except ImportError as err:
	print("Error: %s" %(err))

class OsConf():

	def __init__(self):

		self.basedir=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
		self.cfgfile=self.basedir+'/etc/os.ini'

		if not os.path.exists(self.cfgfile):
			raise Exception('Cannot open file', self.cfgfile)

		self.config = configparser.SafeConfigParser()
		self.config.read(self.cfgfile)
		self.conf = dict(self.config.items('main'))

		try:
			logfile = os.path.expanduser(self.conf['logfile'])
			self.logger = logging.getLogger()
			self.logger.setLevel(logging.DEBUG)
			handler = logging.handlers.TimedRotatingFileHandler(logfile, 'D', 1, 0)
			handler.suffix = "%Y-%m-%d.log"
			formatter = logging.Formatter('%(asctime)s %(levelname)-8s %(message)s', datefmt='%Y-%m-%d %H:%M:%S')
			handler.setFormatter(formatter)
			self.logger.addHandler(handler)
			
		except FileNotFoundError as err:
			print("%s %s" %(err, ''))
			sys.exit(1)
	def list(self, remote = None):
		try:
			#for sect in self.config.sections():
			#	item = dict(self.config.items(sect))
			#	print(sect+ ':')
				#print("\t")
			#	print(item)
				#if 'desc' in item :
				#	print(sect.strip(''), '-',item['desc'])
				#else:
			if remote :
				os.system('cd ' +self.conf['repositories']+'/'+remote+ '; find '+ ' | grep -v .git | sed "s/.\//\//"')
			else:
				os.system('ls -1 ' +self.conf['repositories'])
		except Exception as err:
			print("Error: %s %s" %(err, self.cfgfile))
			sys.exit(1)
	def module(self, mod):
		self.config.read(self.cfgfile)
		item = dict(self.config.items(mod))
		port = int(self.config.get(mod,'port'))
		server = socketserver.UDPServer(('0.0.0.0', port), ShowLog)
		server.serve_forever()
		
	def get(self, remote, filepath):
		source 		= remote+':'+filepath
		destination	= self.conf['repositories']+'/'+remote+''+filepath
		path = os.path.dirname(os.path.expanduser(destination))
		if not os.path.exists(path) :
			os.makedirs(path)
		
		logfile = os.path.expanduser(self.conf['logdir']+'/'+remote+'.'+datetime.today().strftime('%Y-%m-%d.%H:%M:%S')+'.log')
		backup = os.path.expanduser(self.conf['backup']+'/'+remote+'/'+datetime.today().strftime('%Y-%m-%d.%H:%M:%S'))
		
		rsync = Rsync()
		rsync.option(self.option).logfile(logfile).backup(backup).source(source).destination(destination).execute()
		self.logger.debug(rsync.debug());
		
		self.logger.info("get %s %s" % (source, destination))
	def put(self, remote, filepath):
		source 		= self.conf['repositories']+'/'+remote+''+filepath
		destination	= remote+':'+filepath
		
		logfile = os.path.expanduser(self.conf['logdir']+'/'+remote+'.'+datetime.today().strftime('%Y-%m-%d.%H:%M:%S')+'.log')
		backup = self.conf['backup']+'/'+remote+'/'+datetime.today().strftime('%Y-%m-%d.%H:%M:%S')
		rsync = Rsync()
		rsync.option(self.option).logfile(logfile).backup(backup).source(source).destination(destination).execute()
		self.logger.debug(rsync.debug());
		
		self.logger.info("get %s %s" % (source, destination))	
	def edit(self, editor, remote, filepath):
		cmd = "%s %s" % (editor, self.conf['repositories']+'/'+remote+''+filepath)
		os.system(cmd)
	
	def show(self, remote, filepath):
		cmd = "view %s %s" % (editor, self.conf['repositories']+'/'+remote+''+filepath)
		os.system(cmd)
	def daemon(self):
		pid = os.fork()
		if pid > 0:
			sys.exit(0)
	def clone(self, uri):
		source = self.conf['repositories']
		git = Git(source, self.logger)
		git.clone(uri).execute()
	def init(self, directory):
		source = os.path.expanduser(directory)
		if not os.path.exists(source) :
			os.makedirs(source)
		git = Git(source, self.logger)
		git.init().execute()
	def pull(self):
		source = self.conf['repositories']
		git = Git(source, self.logger)
		git.pull().execute()
	def push(self):
		source = self.conf['repositories']
		git = Git(source, self.logger)
		git.push().execute()
	def add(self, file):
		source = self.conf['repositories']
		git = Git(source, self.logger)
		git.add(file).execute()
	def status(self):
		source = self.conf['repositories']
		git = Git(source, self.logger)
		git.status().execute()
	def log(self):
		source = self.conf['repositories']
		git = Git(source, self.logger)
		git.log().execute()
	def commit(self, msg):
		source = self.conf['repositories']
		git = Git(source, self.logger)
		git.commit(msg, '-a').execute()
	def usage(self):
		print("\n  Homepage: http://netkiller.github.io\tAuthor: Neo <netkiller@msn.com>")
	def main(self):
		try:
			parser = OptionParser(usage='usage: %prog [options] node file', version="%prog 1.0.0", description='System Configuration Management')
			parser.add_option('-d','--daemon', dest='daemon', default=False, action='store_true', help='run as daemon')
			#parser.add_option('-l', '--logfile', dest='logfile', default='', metavar='/tmp/test.log', type='str', help='log file')
			parser.add_option('', '--verbose', dest='verbose', default=False, action='store_true', help='increase verbosity')
			#parser.add_option('-s', '--silent', dest='silent', default=False, action='store_true', help="Silent or quiet mode. Don't show progress meter or error messages.")

			group = OptionGroup(parser, "Configuration Management", '')
			group.add_option('-g', '--get', dest='get', default=False, action='store_true', help='get config from remote')
			group.add_option('-p', '--put', dest='put', default=False, action='store_true', help='put config to remote')			
			group.add_option('-l', '--list', dest='list', default=False, action='store_true', help='show module message')
			group.add_option('-s', '--show', dest='show', default=False, action='store_true', help='show content of file')
			group.add_option('-e', '', dest='edit', default=False, metavar='nano', action='store_true', help='default editor is vim')
			group.add_option('', '--edit', dest='edit', default='vi', metavar='nano', choices=['vi','vim','nano'], type='choice', help='choose from vi, vim, nano')
			parser.add_option_group(group)

			group = OptionGroup(parser, "Repositories Management", '')
			group.add_option('', '--init', dest='init', metavar='directory', help='init local repositories')
			group.add_option('', '--clone', dest='clone', metavar='http://domain/project.git', help='clone git repositories')
			group.add_option('', '--pull', dest='pull', default=False, action='store_true', help='pull config from remote repositories')
			group.add_option('', '--push', dest='push', default=False, action='store_true', help='push config to remote repositories')
			group.add_option('', '--add', dest='add', default='', metavar='/path/to/file', type='string',  help='add file to repositories')
			group.add_option('', '--status', dest='status', default=False, action='store_true', help='show status')
			group.add_option('', '--commit', dest='commit', metavar='message', help='commit to local repositories')
			group.add_option('', '--log', dest='log', default=False, action='store_true', help='show log')
			parser.add_option_group(group)

			(options, args) = parser.parse_args()
			
			self.verbose = options.verbose
			if self.verbose :
				self.option = '-azvP'
			else:
				#if options.silent :
				self.option = '-az'
				#else:
				#	self.option = '-azv'
			
			if options.list :
				if len(args) == 1 :
					print(args[0]+":")
					self.list(args[0])
				else:
					self.list()
				sys.exit(1)
			if options.clone :
				self.clone(options.clone)
				sys.exit(1)
			if options.init :
				self.init(options.init)
				sys.exit(1)				
			if options.pull :
				self.pull()
				sys.exit(1)
			if options.push :
				self.push()
				sys.exit(1)
			if options.add :
				self.add(options.add)
				sys.exit(1)	
			if options.status :
				self.status()
				sys.exit(1)
			if options.commit :
				self.commit(options.commit)
				sys.exit(1)
			if options.log :
				self.log()
				sys.exit(1)
			if len(args) == 2 :
				if options.get :
					if options.daemon:
						self.daemon()
					self.get(remote = args[0], filepath = args[1])
					sys.exit(1)
				if options.put : 
					if options.daemon:
						self.daemon()
					self.put(remote = args[0], filepath = args[1])
					sys.exit(1)
				if options.edit == True :
					self.edit(editor = 'vim', remote = args[0], filepath = args[1])
				elif options.edit in ('vi', 'vim', 'nano') :
					self.edit(editor = options.edit, remote = args[0], filepath = args[1])
				elif options.show :
					self.show(remote = args[0], filepath = args[1])
			elif len(args) == 1:
				self.list(remote = args[0])
			else:
				parser.print_help()
				self.usage()
				sys.exit(1)

			if not len(args) == 1:
				parser.print_help()
				self.usage()
				sys.exit(1)

		except Exception as err:
			print("Error: %s %s" %(err, ''))
			sys.exit(1)

if __name__ == '__main__':
	try:
		log = OsConf()
		log.main()
	except KeyboardInterrupt:
		print ("Crtl+C Pressed. Shutting down.")
