#! /usr/bin/env python3
# -*- coding: utf-8 -*-

#	Copyright 2012-2013, Marten de Vries
#
#	This file is part of OpenTeacher.
#
#	OpenTeacher is free software: you can redistribute it and/or modify
#	it under the terms of the GNU General Public License as published by
#	the Free Software Foundation, either version 3 of the License, or
#	(at your option) any later version.
#
#	OpenTeacher is distributed in the hope that it will be useful,
#	but WITHOUT ANY WARRANTY; without even the implied warranty of
#	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#	GNU General Public License for more details.
#
#	You should have received a copy of the GNU General Public License
#	along with OpenTeacher.  If not, see <http://www.gnu.org/licenses/>.

import math
import random

def installQtClasses():
	global KeyboardWidget

	class KeyboardWidget(QtWidgets.QWidget):
		"""An onscreen keyboard view. Make sure you call
		   setKeyboardLayout() before showing the widget (otherwise
		   you'll see nothing.)

		"""
		#15 per row
		SIZE_MAP = [
			#tuples: (start_position, relative_size, finger_number)
			[(0, 1, 1), (1, 1, 1), (2, 1, 2), (3, 1, 3), (4, 1, 4), (5, 1, 4), (6, 1, 7), (7, 1, 7), (8, 1, 8), (9, 1, 9), (10, 1, 10), (11, 1, 10), (12, 1, 10), (13, 2, 10)],
			[(0, 1.5, 1), (1.5, 1, 1), (2.5, 1, 2), (3.5, 1, 3), (4.5, 1, 4), (5.5, 1, 4), (6.5, 1, 7), (7.5, 1, 7), (8.5, 1, 8), (9.5, 1, 9), (10.5, 1, 10), (11.5, 1, 10), (12.5, 1, 10), (13.5, 1.5, 10)],
			[(0, 2, 1), (2, 1, 1), (3, 1, 2), (4, 1, 3), (5, 1, 4), (6, 1, 4), (7, 1, 7), (8, 1, 7), (9, 1, 8), (10, 1, 9), (11, 1, 10), (12, 1, 10), (13, 1, 10), (14, 1, 10)],
			[(0, 1.5, 1), (1.5, 1, 1), (2.5, 1, 1), (3.5, 1, 2), (4.5, 1, 3), (5.5, 1, 4), (6.5, 1, 4), (7.5, 1, 7), (8.5, 1, 7), (9.5, 1, 8), (10.5, 1, 9), (11.5, 1, 10), (12.5, 2.5, 10)],
			[(1.5, 12, (5, 6))],
		]

		_golden_ratio_conjugate = 1.6180339887498948482

		def __init__(self, *args, **kwargs):
			super().__init__(*args, **kwargs)

			self._currentKey = None
			self._wrongKey = None
			self.setSizePolicy(
				QtWidgets.QSizePolicy.Expanding,
				QtWidgets.QSizePolicy.Expanding
			)
			self._h = random.random()
			self._cache = {}
			self._layout = None

		def _colorForFinger(self, finger):
			if finger == (5, 6):
				#I like a non-colored space bar
				return QtCore.Qt.lightGray
			if not finger in self._cache:
				self._cache[finger] = self._nextColor()
			return self._cache[finger]

		def _nextColor(self):
			#calculates a new color, as distinctive from the others as possible
			#credits: http://martin.ankerl.com/2009/12/09/how-to-create-random-colors-programmatically/
			self._h = (self._h + self._golden_ratio_conjugate) % 1
			return QtGui.QColor.fromHsvF(self._h, 0.3, 0.9)

		def paintEvent(self, event):
			if not self._layout:
				#not ready for drawing.
				return
			#make the keyboard as large as possible, but don't let it
			#be partly drawn outside the visible widget area.
			widthCellSize = int(math.floor(self.width() / 15.0)) -1
			heightCellSize = int(math.floor(self.height() / 5.0)) -1
			cellSize = min(widthCellSize, heightCellSize)

			p = QtGui.QPainter()
			p.begin(self)

			for rowNumber, row in enumerate(self.SIZE_MAP):
				y = rowNumber * cellSize
				height = cellSize
				for columnNumber, column in enumerate(row):
					x = cellSize * column[0]
					width = cellSize * column[1]
					finger = column[2]
					text = self._layout[rowNumber][columnNumber]

					#set key background color
					p.setBrush(self._colorForFinger(finger))
					if text == self._currentKey:
						p.setBrush(QtCore.Qt.black)
					elif text == self._wrongKey:
						p.setBrush(QtCore.Qt.red)

					#draw the key background
					p.drawRect(x, y, width, height)

					#if this is the enter key we're drawing, remove the
					#line which separates the two parts of it now the
					#last part of it is drawn.
					if rowNumber +1 == 3 and columnNumber == len(row) -1:
						p.setPen(self._colorForFinger(finger))
						#x + 1 because it looks better
						p.drawLine(x + 1, y, x + width, y)
						p.setPen(QtGui.QPen())

					#reset the background color
					p.setBrush(QtGui.QBrush())
					if text in (self._currentKey, self._wrongKey):
						#set the text color
						p.setPen(QtCore.Qt.white)
					#draw the text onto the key
					p.drawText(QtCore.QRect(x, y, width, height), QtCore.Qt.AlignCenter, text)
					#reset the text color to the default
					p.setPen(QtGui.QPen())

			p.end()

		def setCurrentKey(self, key):
			self._currentKey = key
			self.update()

		def setWrongKey(self, key):
			self._wrongKey = key
			self.update()

		def sizeHint(self):
			return QtCore.QSize(500, 210)

		def setKeyboardLayout(self, layout):
			self._layout = layout
			self.update()

class TypingTutorKeyboardModule:
	def __init__(self, moduleManager, *args, **kwargs):
		super().__init__(*args, **kwargs)
		self._mm = moduleManager

		self.type = "typingTutorKeyboard"
		self.requires = (
			self._mm.mods(type="ui"),
		)

	def createKeyboardWidget(self, *args, **kwargs):
		return KeyboardWidget(*args, **kwargs)

	def enable(self):
		global QtCore, QtGui, QtWidgets
		try:
			from PyQt5 import QtCore, QtGui, QtWidgets
		except ImportError:
			return

		installQtClasses()

		self.active = True

	def disable(self):
		self.active = False

def init(moduleManager):
	return TypingTutorKeyboardModule(moduleManager)
