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

#	Copyright 2011-2012, Milan Boers
#	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 contextlib

def installQtClasses():
	global EnterMap, EnterMapScene, Map, TeachPictureMap, TeachPictureScene, TeachPlaceOnMap

	class Map(QtWidgets.QGraphicsView):
		"""Abstract class for the map widgets"""

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

			if QtOpenGL and base._openGlSetting["value"]:
				self.setViewport(QtOpenGL.QGLWidget())

		def setMap(self, map):
			self._setPicture(map)

		def _setPicture(self,picture):
			# Create a new scene
			self.scene = QtWidgets.QGraphicsScene()
			# Set the pixmap of the scene
			self.pixmap = QtGui.QPixmap(picture)
			self.scene.addPixmap(self.pixmap)
			# Set the scene
			self.setScene(self.scene)

		def wheelEvent(self,wheelevent):
			# Scrolling makes it zoom
			if wheelevent.angleDelta().y() > 0:
				self.scale(1.1,1.1)
			else:
				self.scale(0.9,0.9)

	class TeachPlaceOnMap(QtWidgets.QGraphicsRectItem):
		"""A place on the map for the inverted order"""

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

			width = 10
			height = 10

			self.setRect(place["x"] - width / 2, place["y"] - height / 2, width, height)
			self.setBrush(QtGui.QBrush(QtGui.QColor("red")))

			self.place = place

	class EnterMapScene(QtWidgets.QGraphicsScene):
		"""The graphics scene of the map where you enter"""

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

			self.enterMap = enterMap

		def mouseDoubleClickEvent(self,gsme):
			# Get coordinates
			x = gsme.lastScenePos().x()
			y = gsme.lastScenePos().y()
			# If its in the map
			if x > 0 and y > 0:
				# Ask for the name
				name = QtWidgets.QInputDialog.getText(self.enterMap, _("Name for this place"), _("What's this place's name?"))
				if name[1] and name[0].strip() != u"":
					# Make the place
					place = {
						"id": int(),
						"name": name[0].strip(),
						"x": int(x),
						"y": int(y)
					}
					# Set id
					try:
						place["id"] = self.enterMap.enterWidget.list["items"][-1]["id"] + 1
					except IndexError:
						place["id"] = 0
					# And add the place
					self.enterMap.enterWidget.addPlace(place)

	class EnterMap(Map):
		"""The map on the enter tab"""

		def __init__(self, enterWidget, *args, **kwargs):
			super().__init__(*args, **kwargs)
			# Make it scrollable and draggable
			self.setDragMode(QtWidgets.QGraphicsView.ScrollHandDrag)

			self.enterWidget = enterWidget

			self.placesList = []
			self.placesGroup = QtWidgets.QGraphicsItemGroup()

		def _setPicture(self, filepath):
			"""Override base class _setPicture with one that uses an
			   EnterMapScene instead of QGraphicsScene

			"""
			# Create a new scene
			self.scene = EnterMapScene(self)
			# Set the pixmap of the scene
			self.pixmap = QtGui.QPixmap(filepath)
			self.scene.addPixmap(self.pixmap)
			# Set the scene
			self.setScene(self.scene)

		def update(self):
			# Remove previous items
			for item in self.placesList:
				with contextlib.suppress(RuntimeError):
					#RuntimeError: Object already removed
					self.scene.removeItem(item)

			# Remove all previous items
			self.placesList = []

			# Add all the places
			for place in self.enterWidget.list["items"]:
				# Make the little rectangle
				rect = QtWidgets.QGraphicsRectItem(place["x"],place["y"],6,6)
				rect.setBrush(QtGui.QBrush(QtGui.QColor("red")))
				# Place the rectangle in the list of items
				self.placesList.append(rect)

				# Make the shadow of the text
				shadow = QtWidgets.QGraphicsTextItem(place["name"])
				shadow.setFont(QtGui.QFont("sans-serif",15,75))
				shadow.setPos(place["x"]+2,place["y"]+2)
				shadow.setDefaultTextColor(QtGui.QColor("black"))
				shadow.setOpacity(0.5)
				# Place the shadow in the list of items
				self.placesList.append(shadow)

				item = QtWidgets.QGraphicsTextItem(place["name"])
				item.setFont(QtGui.QFont("sans-serif",15,75))
				item.setPos(place["x"],place["y"])
				item.setDefaultTextColor(QtGui.QColor("red"))
				# Place the text in the list of items
				self.placesList.append(item)

			# Place the list of items on the map
			self.placesGroup = self.scene.createItemGroup(self.placesList)

		def getScreenshot(self):
			image = QtGui.QImage(self.scene.width(), self.scene.height(), QtGui.QImage.Format_RGB32)
			image.fill(QtGui.QColor(QtCore.Qt.white).rgb())
			painter = QtGui.QPainter(image)
			self.scene.render(painter)
			painter.end()
			return image

	class TeachPictureScene(QtWidgets.QGraphicsScene):
		"""Scene for the TeachPictureMap"""

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

			self.pictureMap = pictureMap

		def mouseReleaseEvent(self, event):
			# Clicked a place
			clickedObject = self.itemAt(event.lastScenePos().x(), event.lastScenePos().y(), QtGui.QTransform())
			if clickedObject.__class__ == TeachPlaceOnMap:
				self.pictureMap.teachWidget.lesson.checkAnswer(clickedObject.place)

	class TeachPictureMap(Map):
		"""The map on the teach tab"""

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

			self.teachWidget = teachWidget

			# Not interactive
			self.interactive = False
			# Make sure everything is redrawn every time
			self.setViewportUpdateMode(0)

		def setArrow(self, x, y):
			"""Sets the arrow on the map to the right position"""

			self.centerOn(x-15,y-50)
			self.crosshair.setPos(x-15,y-50)

		def removeArrow(self):
			"""Removes the arrow"""

			self.scene.removeItem(self.crosshair)

		def _setPicture(self,picture):
			"""Overriding the base class _setPicture method with one using the TeachPictureScene"""

			# Create a new scene
			self.scene = TeachPictureScene(self)
			# Set the pixmap of the scene
			self.pixmap = QtGui.QPixmap(picture)
			self.scene.addPixmap(self.pixmap)
			# Set the scene
			self.setScene(self.scene)

		def showPlaceRects(self):
			"""Shows all the places without names"""

			placesList = []

			for place in self.teachWidget.places["items"]:
				# Make the little rectangle
				rect = TeachPlaceOnMap(place)
				# Place the rectangle in the list of items
				placesList.append(rect)

			self.placesGroup = self.scene.createItemGroup(placesList)

		def hidePlaceRects(self):
			with contextlib.suppress(AttributeError):
				for item in self.placesList:
					self.removeItem(item)

		def setInteractive(self, val):
			if val:
				self.showPlaceRects()
				# Interactive
				self.interactive = True
				# Scrollbars
				self.setDragMode(QtWidgets.QGraphicsView.ScrollHandDrag)
				self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
				self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
			else:
				self.hidePlaceRects()
				# Not interactive
				self.interactive = False
				# No scrollbars
				self.setDragMode(QtWidgets.QGraphicsView.NoDrag)
				self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
				self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
				# Arrow
				crosshairPixmap = QtGui.QPixmap(base._mm.resourcePath("resources/crosshair.png"))
				self.crosshair = QtWidgets.QGraphicsPixmapItem(crosshairPixmap)

				self.scene.addItem(self.crosshair)

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

		global base
		base = self

		self._mm = moduleManager

		self.type = "topoMaps"
		self.priorities = {
			"default": 416,
		}

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

		self.uses = (
			self._mm.mods(type="translator"),
			self._mm.mods(type="settings"),
		)
		self.filesWithTranslations = ("topoMaps.py",)

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

		self._modules = set(self._mm.mods(type="modules")).pop()

		# Add settings
		try:
			assert QtOpenGL is not None
			self._settings = self._modules.default(type="settings")
		except (AssertionError, IndexError):
			self._openGlSetting = {"value": False}
		else:
			self._openGlSetting = self._settings.registerSetting(**{
				"internal_name": "org.openteacher.lessons.topo.opengl",
				"type": "boolean",
				"defaultValue": False,
				"advanced": True,
			})

		#setup translation
		try:
			translator = self._modules.default("active", type="translator")
		except IndexError:
			pass
		else:
			translator.languageChanged.handle(self._retranslate)
		self._retranslate()

		self.active = True

	def _retranslate(self):
		#install _ and ngettext
		global _
		global ngettext

		try:
			translator = self._modules.default("active", type="translator")
		except IndexError:
			_, ngettext = str, lambda a, b, n: a if n == 1 else b
		else:
			_, ngettext = translator.gettextFunctions(
				self._mm.resourcePath("translations")
			)

		self._openGlSetting.update({
			"name": _("OpenGL rendering"),
			"category": _("Lesson"),
			"subcategory": _("Topography"),
		})

	def disable(self):
		self.active = False

		del self._modules
		if hasattr(self, "_settings"):
			del self._settings
		del self._openGlSetting

	def getEnterMap(self, enterWidget):
		return EnterMap(enterWidget)

	def getTeachMap(self, teachWidget):
		return TeachPictureMap(teachWidget)

def init(moduleManager):
	return TopoMapsModule(moduleManager)
