class ConferenceTimetableBot(object):
	"""docstring for ConferenceTimetableBot"""
	def __init__(self):
		super(ConferenceTimetableBot, self).__init__()
		self.server_params = ServerParameters(savefile_name=SERVER_PARAMS_SAVEFILE_NAME,
											  initial_params=INITIAL_SERVER_PARAMS
											  )
		self.bot = telegramHigh(BOT_TOKEN)
		self.user_params = UserParams(filename="conference_timetable_userparams", initial=INITIAL_SUBSCRIBER_PARAMS)
		self.timetable_db = TimetableDatabase("timetable",self.server_params)

		# starts the main loop
		self.bot.start(processingFunction=self.processUpdate
					, periodicFunction=self.periodicFunction
					# , termination_function=self.termination_function
					)

	def assignBotLanguage(self, chat_id, language):
		"""
		Assigns bot language to a subscribers list and saves to disk
		:param language:
		:param chat_id:
		:return: None
		"""
		self.user_params.setEntry(chat_id=chat_id, param="lang", value=language)

	def periodicFunction(self):
		bot = self.bot

		# process reminders
		# Get reminder data from DB
		reminders = self.timetable_db.getUnnotifiedSubscriptions()

		for event in reminders:
			chat_id = event[0]
			event_id = event[1]
			status = event[2]
			event_time = TimetableDatabase.stringTimeToDatetime(event[3])
			cur_time = self.timetable_db.getOffsetTime()
			event_name = self.timetable_db.getEventData(event_id)['name']

			if status < 2:
				# this event still has reminders
				if (cur_time-event_time).days >= 0:
					# Remind when an event starts
					if self.user_params.getEntry(chat_id, 'subscribed') == 1:
						bot.sendMessage(chat_id=chat_id
									, message="{0} is starting now! \n/event{1}".format(event_name, event_id)
									, key_markup="Same"
							)
					self.timetable_db.setReminderStatus(chat_id, event_id, 2)
			if status < 1:
				# preliminary reminder is not triggered yet
				remind_period = self.user_params.getEntry(chat_id,'remind_period')
				till_event_delta = event_time-cur_time
				if self.user_params.getEntry(chat_id,'subscribed') == 1 \
					and till_event_delta.days == 0 \
					and till_event_delta.seconds <= remind_period * 60:
					# Set status to 1 and trigger preliminary reminder
					self.timetable_db.setReminderStatus(chat_id, event_id, 1)
					bot.sendMessage(chat_id=chat_id
									, message="{0} is starting in {2} minutes!\n/event{1}"
									.format(event_name, event_id,till_event_delta.seconds//60)
									, key_markup="Same"
							)


			#Cleanup of all status 2... or maybe not


	def processUpdate(self, u):
		bot = self.bot
		Message = u.message
		message = Message.text
		message_id = Message.message_id
		chat_id = Message.chat_id

		subs = self.user_params

		subs.initializeUser(chat_id=chat_id, data=INITIAL_SUBSCRIBER_PARAMS)

		# language support class for convenience
		LS = LanguageSupport(subs.getEntry(chat_id=chat_id, param="lang"))
		lS = LS.languageSupport
		allv = LS.allVariants
		MMKM = lS(MAIN_MENU_KEY_MARKUP)

		if message == "/start":
			bot.sendMessage(chat_id=chat_id
							, message=lS(START_MESSAGE)
							, key_markup=MMKM
							)
		elif message == "/help" or message in allv(HELP_BUTTON):
			bot.sendMessage(chat_id=chat_id
							, message=lS(HELP_MESSAGE).format(lS(GET_TIMETABLE_BUTTON), lS(ALL_DAYS_BUTTON),
															  lS(MY_EVENTS_BUTTON), lS(SUBSCRIBE_BUTTON))
							, key_markup=MMKM
							, markdown=True
							)
		elif message == "/about" or message in allv(ABOUT_BUTTON):
			bot.sendMessage(chat_id=chat_id
							, message=lS(ABOUT_MESSAGE).format(".".join([str(i) for i in VERSION_NUMBER]))
							, key_markup=MMKM
							, markdown=True
							)
		elif message == "/otherbots" or message in allv(OTHER_BOTS_BUTTON):
			bot.sendMessage(chat_id=chat_id
							, message=lS(OTHER_BOTS_MESSAGE)
							, key_markup=MMKM
							)
		elif message == "/map" or message in allv(MAP_BUTTON):
			map_filepath = path.join(SCRIPT_FOLDER, RESOURCES_FOLDER_NAME, MAP_FILENAME)
			if path.isfile(map_filepath):
				bot.sendPic(chat_id=chat_id
						, pic=open(map_filepath, "rb")
						, caption=MAP_MESSAGE
								)
			else:
				# There is no map file, notify user
				bot.sendMessage(chat_id=chat_id
							, message=lS(NO_MAP_FILE_MESSAGE)
							, key_markup=MMKM
							)
		elif message == "/timetable" or message in allv(GET_TIMETABLE_BUTTON):
			bot.sendMessage(chat_id=chat_id
							, message=lS(GET_TIMETABLE_MESSAGE)
							, key_markup=self.timetable_db.getTimetableMarkup()
							)
		elif TimetableDatabase.isDate(message):
			# it is a date, show day timetable
			print('message', message)
			response = lS(CURRENT_TIME_MESSAGE).format(self.timetable_db.getOffsetTime().strftime("%H:%M")) \
			+ "\n\n" \
			+ self.timetable_db.getDayTimetable(message)
			bot.sendMessage(chat_id=chat_id
							, message=response
							, key_markup=MMKM
							)
			#If a graphical file in format YYYY-MM-DD.png exists, send it as well
			try:
				filepath = path.join(SCRIPT_FOLDER, RESOURCES_FOLDER_NAME, message) + ".png"
				with open(filepath, "rb") as pic:
						bot.sendPic(chat_id=chat_id
						, pic=pic
						, caption=message
								)
			except FileNotFoundError as e:
				print("Graph file not found")
				print(full_traceback())

		elif message == '/all' or message in allv(ALL_DAYS_BUTTON):
			# it is a date, show day timetable
			response = lS(CURRENT_TIME_MESSAGE).format(self.timetable_db.getOffsetTime().strftime("%H:%M")) \
			+ "\n\n" \
			+ self.timetable_db.getAllDaysTimetable()

			bot.sendMessage(chat_id=chat_id
							, message=response
							, key_markup=MMKM
							)
		elif re.match("^/event[0-9]+$", message):
			# Event link is pressed
			event_info = self.timetable_db.getEventInfo(message[6:])
			response = lS(CURRENT_TIME_MESSAGE).format(self.timetable_db.getOffsetTime().strftime("%H:%M")) \
			+ "\n\n" \
			+ lS(event_info)
			bot.sendMessage(chat_id=chat_id
						, message=response
						, key_markup=MMKM
						, markdown="html"
						)
		elif message == "/subscribe" or message in allv(SUBSCRIBE_BUTTON):
			if self.user_params.getEntry(chat_id, "subscribed") == 0:
				self.user_params.setEntry(chat_id, "subscribed", 1)
				bot.sendMessage(chat_id=chat_id
							, message=lS(SUBSCRIBED_MESSAGE)
							, key_markup=MMKM
							)
			else:
				bot.sendMessage(chat_id=chat_id
							, message=lS(ALREADY_SUBSCRIBED_MESSAGE)
							, key_markup=MMKM
							)
		elif message == "/unsubscribe" or message in allv(UNSUBSCRIBE_BUTTON):
			if self.user_params.getEntry(chat_id, "subscribed") == 1:
				self.user_params.setEntry(chat_id, "subscribed", 0)
				bot.sendMessage(chat_id=chat_id
							, message=lS(UNSUBSCRIBED_MESSAGE)
							, key_markup=MMKM
							)
			else:
				bot.sendMessage(chat_id=chat_id
							, message=lS(ALREADY_UNSUBSCRIBED_MESSAGE)
							, key_markup=MMKM
							)
		elif message == "/myevents" or message in allv(MY_EVENTS_BUTTON):
			# show a table of events to which a user is subscribed
			user_timetable = self.timetable_db.getUserTimetable(chat_id=chat_id)
			if user_timetable:
				response = lS(CURRENT_TIME_MESSAGE).format(self.timetable_db.getOffsetTime().strftime("%H:%M")) \
				+ "\n\n" \
				+ self.timetable_db.getUserTimetable(chat_id=chat_id)
			else:
				response = "Your personal timetable is empty!"

			bot.sendMessage(chat_id=chat_id
				, message=response
				, key_markup=MMKM
				)

		elif re.match("^/sub[0-9]+$",message):
			event_index = message[4:]
			if self.timetable_db.eventIndexExists(event_index):
				# Event exists
				event_name = self.timetable_db.getEventData(event_index)['name']
				if not self.timetable_db.subscriptionExists(chat_id, event_index):
					self.timetable_db.addSubscription(chat_id, event_index)
					bot.sendMessage(chat_id=chat_id
									, message="You have subscribed to the event: {0}".format(event_name, event_index)
									, key_markup=MMKM
									)
				else:
					self.timetable_db.deleteSubscription(chat_id,event_index)
					bot.sendMessage(chat_id=chat_id
									, message="Subscription deleted: {0}".format(event_name, event_index)
									, key_markup=MMKM
									)
			else:
				# such event doesn't exist
				bot.sendMessage(chat_id=chat_id
							, message="Event with index {0} doesn't exist!".format(event_index)
							, key_markup=MMKM
							, reply_to=message_id
							)
		elif re.match("^[0-9]+$",message):
			remind_period = int(message)
			if remind_period < 1:
				self.user_params.setEntry(chat_id, 'remind_period', 1)
				bot.sendMessage(chat_id=chat_id
							, message="The minimum remind period possible is 1 minute. Setting to 1 minute."
							, key_markup=MMKM
							)
			elif remind_period > 1439:
				self.user_params.setEntry(chat_id, 'remind_period', 1439)
				bot.sendMessage(chat_id=chat_id
							, message="The minimum remind period possible is 1439 minutes. Setting to 1439 minutes."
							, key_markup=MMKM
							)
			else:
				self.user_params.setEntry(chat_id, 'remind_period', remind_period)
				bot.sendMessage(chat_id=chat_id
							, message="Preliminary reminder period has been set to {0}".format(message)
							, key_markup=MMKM
							)
		elif message == RU_LANG_BUTTON:
			self.assignBotLanguage(chat_id, 'RU')
			LS = LanguageSupport(subs.getEntry(chat_id=chat_id, param="lang"))
			key_markup = LS.languageSupport(message=MAIN_MENU_KEY_MARKUP)
			bot.sendMessage(chat_id=chat_id
							, message="Сообщения бота будут отображаться на русском языке."
							, key_markup=key_markup
							)
		elif message == EN_LANG_BUTTON:
			self.assignBotLanguage(chat_id, 'EN')
			LS = LanguageSupport(subs.getEntry(chat_id=chat_id, param="lang"))
			key_markup = LS.languageSupport(message=MAIN_MENU_KEY_MARKUP)
			bot.sendMessage(chat_id=chat_id
							, message="Bot messages will be shown in English."
							, key_markup=key_markup
							)

		# admin tools
		elif bot.isDocument(u) and self.user_params.getEntry(chat_id, 'admin') == 1:
			# check if it is a timetable
			if re.search("^.*{0}$".format(EVENT_TIMETABLE_FILENAME), bot.getDocumentFileName(u)):
				# It's a text file with timetable
				full_path = path.join(TEMP_FOLDER, EVENT_TIMETABLE_FILENAME)
				bot.downloadFile(bot.getFileID(u), full_path)

				try:
					with open(full_path, "r") as f:
						data = f.read()
						print(data)
						self.timetable_db.parseTimetable(data)

					os.remove(full_path)

					bot.sendMessage(chat_id=chat_id
								, message="Events added!"
								, key_markup=MMKM
								)
				except IndexError:
						bot.sendMessage(chat_id=chat_id
								, message="Parsing failed! Are all fields present in the file?"
								, key_markup=MMKM
								)
			if re.search("^.*{0}$".format(EVENT_TIMETABLE_XLS_FILENAME), bot.getDocumentFileName(u)):
				# It's a XLS sheet with a timetable
				full_path = path.join(TEMP_FOLDER, EVENT_TIMETABLE_XLS_FILENAME)
				bot.downloadFile(bot.getFileID(u), full_path)

				self.timetable_db.parseTimetableXLS(full_path)
				os.remove(full_path)

				bot.sendMessage(chat_id=chat_id
								, message="Events added!"
								, key_markup=MMKM
								)

		elif re.match("^TZ(\+|-)([0-9]|[0-1][0-9]|2[0-3])$", message) and self.user_params.getEntry(chat_id, 'admin') == 1:
			# Setting the timezone parameter
			timezone = int(message[2:])
			self.server_params.setParam('timezone', timezone)
			bot.sendMessage(chat_id=chat_id
							, message="Timezone set to UTC{0}{1}".format("+" if timezone >= 0 else "", timezone)
							, key_markup=MMKM
							)
		elif message == "/revoke" and self.user_params.getEntry(chat_id, 'admin') == 1:
			# revoke admin rights
			self.user_params.setEntry(chat_id, 'admin', 0)
			bot.sendMessage(chat_id=chat_id
							, message="Admin rights revoked"
							, key_markup=MMKM
							)
		else:
			bot.sendMessage(chat_id=chat_id
							, message="Unknown command!"
							, key_markup=MMKM
							)