import sys
from ftplib import FTP
import csv
import os, subprocess

class Update():

	serverFtp = 'firmware.beamian.com'
	userFtp = 'firmware@beamian.com'
	passwordFtp = "}8ClC&yA!%X#}t50HV"

	currentConfig = "config.txt"
	pathNewConfig = '.newConfig/'

	pathConfig   = ''
	fileConfig   = 'config.txt'
	pathUploadConfig = 'config/'

	newDataZip     = os.path.dirname(os.path.realpath(__file__)) + '/newData.zip'
	newFirmwareZip = os.path.dirname(os.path.realpath(__file__)) + '/../newFirmware.zip'
	newConfigZip   = os.path.dirname(os.path.realpath(__file__)) + '/../newConfig.zip'

	def __init__(self):
		self.beamianId = 'B3999'
		self.server_data = ''
		self.server_firmware = ''
		self.server_data_str = ''
		self.server_firmware_str = ''
		self.id = 'B3999'
		self.companyName = ''

		self.readConfig()
		self.mac = subprocess.check_output(['cat', '/sys/class/net/wlan0/address']).replace('\"','').replace('\n','')
		self.loadTime()

	def loadTime(self):
		os.system("sed -i '/run\/systemd\/system/{n;s/.*/#   exit 0/}' /lib/udev/hwclock-set")
		os.system("hwclock --hctosys")

	def updateTime(self):
		#ntp is not woking
		#os.system("service ntp stop")
		#_DATE=$(curl --connect-timeout 10 -s --head http://google.com | grep ^Date: | sed 's/Date: //g');
		#if [ -n "$_DATE" ]; then
		#    date -s "$_DATE";
		#    hwclock --systohc;
		#fi;
		os.system("_DATE=$(curl --insecure --connect-timeout 10 -s --head http://google.com | grep ^Date: | sed 's/Date: //g'); if [ -n \"$_DATE\" ]; then date -s \"$_DATE\"; hwclock --systohc; fi;")

	def newBeamianId(self, id):

		print('newbeamianid' + id)
		if id[:2] != 'B2' and id[:2] != 'B3' and id[:2] != 'B4':
			return False

		self.beamianId = id
		self.id = id[2:]
		os.system("sed -i '/^127/ s/B.\+/B" + id[1:] + " /g' /etc/hosts");
		os.system("echo B" + id[1:] + ">/etc/hostname");
		self.writeConfig()
		print('New Beamian ID: ' + id)

		return True

	def getBeamianId(self):
		return self.beamianId.upper()

	def getId(self):
		return self.id.upper()

	def setId(self, id=None):
		if id == None or id == '':
			id = self.getBeamianId()[2:]

		self.id = id
		self.writeConfig()
		print('New ID: ' + id)

	def setCompanyName(self, name=None):
		if name ==None:
			name = ''
		self.companyName = name
		self.writeConfig()

	def getCompanyName(self):
		return self.companyName

	def getMac(self):
		return self.mac.upper()

	def checkUpdates(self):

		localFileConfigPath= '/tmp/beamian_' + self.fileConfig

		r, msg = self.downloadFile(self.pathConfig + self.fileConfig, localFileConfigPath)

		if r == True:
			with open(localFileConfigPath, 'rb') as csvfile:
				lines = csv.reader(csvfile, delimiter=',')
				lines = filter(None, lines)
				for l in lines:
					if l != None and l[0] != None and l[0] == self.beamianId:
						self.server_data         = l[1]
						self.server_firmware     = l[2]
						self.server_data_str     = l[3]
						self.server_firmware_str = l[4]

				if self.server_data == None or self.server_firmware == None:
					return None, None, 'ID not found'
				else:
					if self.server_data != '' and self.server_firmware != '' and self.current_data != self.server_data and self.current_firmware != self.server_firmware :
						return self.server_firmware_str, self.server_data_str, 'New update available'
					elif self.server_data != '' and self.current_data != self.server_data:
						return None, self.server_data_str, 'New data available'
					elif self.server_firmware != '' and self.current_firmware != self.server_firmware:
						return self.server_firmware_str, None, 'New firmware available'
					else:
						return None, None, 'Nothing to update'
		else:
			return None, None, msg

	def downloadFile(self, server_path, local_path):
		try:
			ftp = FTP(self.serverFtp)
			ftp.login(self.userFtp, self.passwordFtp)

			f = open(local_path, 'wb')
			ftp.retrbinary('RETR ' + server_path, f.write)
			f.close()

			ftp.quit()
			return True, 'File retrieved'

		except Exception, e:
			errorMsg = str(e)
			return False, errorMsg[errorMsg.find("]") + 1:]

	def sendFile(self, local_path, server_path):
		try:
			ftp = FTP(self.serverFtp)
			ftp.login(self.userFtp, self.passwordFtp)

			f = open(local_path, 'rb')
			ftp.storbinary('STOR ' + server_path, f)
			f.close()

			ftp.quit()

			return True, 'File uploaded'

		except Exception, e:
			errorMsg = str(e)
			return False, errorMsg[errorMsg.find("]") + 1:]

	def loadNewData(self):
		try:
			if os.path.exists(self.newDataZip):
				os.system("unzip -o " + self.newDataZip)
				os.system("rm -f " + self.newDataZip)
				#self.current_data = self.server_data
				self.writeConfig()
				print("New data installed!")
				return True, "New data installed!"
		except:
			print("Error installing new data")
			return False, "Error installing new data"

		print("No data to update")
		return False, "No data to update"

	def updateData(self):
		print(self.server_data)
		r, msg = self.downloadFile(self.pathConfig + self.server_data, self.newDataZip)

		if r:
			#os.system("unzip -o " + self.newDataZip)
			#os.system("rm -f " + self.newDataZip)
			self.current_data = self.server_data
			self.writeConfig()
			return True, "New data received"
		else:
			return False, msg

	def updateFirmware(self):
		r, msg = self.downloadFile(self.pathConfig + self.server_firmware, self.newFirmwareZip)
		if r:

			os.system("rm -f "  + self.newConfigZip)
			os.system("rm -rf "  + self.pathNewConfig)
			os.system("mkdir "   + self.pathNewConfig)
			os.system("cp -r data " + self.pathNewConfig)

			self.writeConfigFile(self.pathNewConfig + self.currentConfig, self.beamianId, self.server_data, self.server_firmware, self.server_data_str, self.server_firmware_str)
			#os.system("cp "      + self.currentConfig + " " + self.pathNewConfig)

			os.system("cd " + self.pathNewConfig + "; zip -r " + self.newConfigZip + " *")
			os.system("rm -rf "  + self.pathNewConfig)

			return True, "New Firmware downloaded"
		else:
			return False, msg


	def readConfig(self):
		beamianId, data, firmware, data_str, firmware_str, id, companyName =  self.readConfigFile(self.currentConfig)
		if beamianId!=None:
			self.beamianId            = beamianId
			self.current_data         = data
			self.current_firmware     = firmware
			self.current_data_str     = data_str
			self.current_firmware_str = firmware_str

			self.setId(id)
			self.setCompanyName(companyName)

	def readConfigFile(self, filename):
		with open(filename, 'rb') as csvfile:
			lines = csv.reader(csvfile, delimiter=',')
			lines = filter(None, lines)
			l = lines[0]

			if l != None and l != "" and len(l) >= 7:
				return l[0], l[1], l[2], l[3], l[4], l[5], l[6]
			elif l != None and l != "" and len(l) <=5:
				return l[0], l[1], l[2], l[3], l[4], None, None
			else:
				return None, None, None, None, None, None, None

	def writeConfigFile(self, filename, bid, data, firmware, data_str, firmware_str, id='', cname=''):
		with open(filename, 'wb') as csvfile:
			lines = csv.writer(csvfile, delimiter=',')
			lines.writerow([bid, data, firmware, data_str, firmware_str, id, cname])


	def writeConfig(self):
		self.writeConfigFile(self.currentConfig, self.beamianId, self.current_data, self.current_firmware, self.current_data_str, self.current_firmware_str, self.id, self.companyName)

	def sendConfig(self):
		localFile= '/tmp/beamian_id.txt'
		serverFile = self.pathUploadConfig + '/' + self.beamianId + ".txt"

		#mac = subprocess.check_output(['cat', '/sys/class/net/wlan0/address']).replace('\"','').replace('\n','')
		#mac = subprocess.check_output(['cat', '/sys/class/net/wls1/address']).replace('\"','').replace('\n','')

		with open(localFile, 'wb') as csvfile:
			lines = csv.writer(csvfile, delimiter=',')

			lines.writerow([self.beamianId, self.current_data, self.current_firmware, self.current_data_str, self.current_firmware_str, self.id, self.companyName, self.mac])

		r, msg = self.sendFile(localFile, serverFile)

		if r:
			return 'Configuration file sent'
		else:
			return msg


#u=Update()
#u.checkUpdates()
#print(u.updateFirmware())
