import assets
from api import API
from webview import WebView
from PyQt5.QtCore import QObject, QByteArray, QBuffer, pyqtSlot, pyqtSignal
from PyQt5.Qt import Qt, QApplication, QDialog, QEvent, QPalette, QPainter, QImage, QIcon

class Window(QDialog):

	Move			 = 0b0000
	ResizeTop		 = 0b0001
	ResizeRight		 = 0b0010
	ResizeBottom	 = 0b0100
	ResizeLeft		 = 0b1000

	onshow			 = pyqtSignal()
	onhide			 = pyqtSignal()
	onfocus			 = pyqtSignal()
	onblur			 = pyqtSignal()
	onclose			 = pyqtSignal()
	onmove			 = pyqtSignal(int, int, int, int)
	onresize		 = pyqtSignal(int, int, int, int)
	onstatechange	 = pyqtSignal()
	onmouseenter	 = pyqtSignal()
	onmouseleave	 = pyqtSignal()

	def __init__(self, parent = None, url = '', width = None, height = None, isDialog = False):
		super(Window, self).__init__(parent if isDialog else None)
		assets.windows.append(self)
		if width is None:
			width = assets.manifest['width']
		if height is None:
			height = assets.manifest['height']
		windowFlags = Qt.WindowTitleHint | Qt.WindowSystemMenuHint | Qt.WindowMinimizeButtonHint | Qt.WindowMaximizeButtonHint | Qt.WindowCloseButtonHint
		if isDialog:
			windowFlags |= Qt.Dialog
		else:
			windowFlags |= Qt.CustomizeWindowHint
		self.dragParams = {'type': 0, 'x': 0, 'y': 0, 'size': 5, 'margin': 0, 'draging': False}
		self.webView = WebView(self, url)
		self.api = API(self)
		self.parent = parent
		self.resize(width, height)
		self.setMouseTracking(True)
		self.setWindowFlags(windowFlags)
		self.setWindowTitle('Hybrid App Engine')
		self.setAttribute(Qt.WA_QuitOnClose, True)
		self.setAttribute(Qt.WA_DeleteOnClose, True)
		self.setAttribute(Qt.WA_TranslucentBackground, True)
		self.setVisible(assets.manifest['visible'])
		self.setResizable(assets.manifest['resizable'])
		self.setFrameless(assets.manifest['frameless'])
		self.setWindowIcon(QIcon(assets.manifest['icon']))
		self.setTransBackground(assets.manifest['transBackground'])

	# Methods

	def setWindowFlags(self, windowFlags):
		visible = self.isVisible()
		super(Window, self).setWindowFlags(windowFlags)
		if visible:
			self.show()

	def testWindowFlags(self, windowFlags):
		return self.windowFlags() & windowFlags

	def getCursorType(self, x, y):
		width = self.width()
		height = self.height()
		size = self.dragParams['size']
		margin = self.dragParams['margin']
		isResizableX = self.isResizableX()
		isResizableY = self.isResizableY()
		cursorType = Window.Move
		if x >= margin and x <= width - margin and y >= margin and y <= height - margin:
			if y <= size + margin and isResizableY:
				cursorType |= Window.ResizeTop
			elif y >= height - margin - size and isResizableY:
				cursorType |= Window.ResizeBottom
			if x <= size + margin and isResizableX:
				cursorType |= Window.ResizeLeft
			elif x >= width - margin - size and isResizableX:
				cursorType |= Window.ResizeRight
		return cursorType

	# Slots

	# 获取父窗口
	@pyqtSlot(result = QObject)
	def opener(self):
		return self.parent

	# 任务栏闪烁
	@pyqtSlot()
	@pyqtSlot(int)
	def alert(self, msec = 0):
		QApplication.alert(self, msec)

	# 执行简单的JS
	@pyqtSlot(str, result = QObject)
	def eval(self, javaScript):
		obj = QObject(self)
		obj.setObjectName('evalResult')
		obj.setProperty('result', self.webView.eval(javaScript))
		print(dir(self.onstatechange))
		return obj

	# 截图
	@pyqtSlot(result = str)
	@pyqtSlot(bool, result = str)
	@pyqtSlot(bool, str, result = bool)
	def capture(self, fullScreen = False, filename = ''):
		if fullScreen:
			image = QApplication.primaryScreen().grabWindow(0)
		else:
			image = QImage(self.webView.mainFrame.contentsSize(), QImage.Format_ARGB32)
			painter = QPainter(image)
			self.webView.mainFrame.render(painter)
			painter.end()
		if filename:
			return image.save(filename)
		else:
			data = QByteArray()
			buffer = QBuffer(data)
			buffer.open(QBuffer.WriteOnly)
			image.save(buffer, 'PNG')
			return bytes(data.toBase64()).decode()

	# 打开开发者工具
	@pyqtSlot()
	def showInspector(self):
		self.webView.page().showInspector()

	# 关闭开发者工具
	@pyqtSlot()
	def hideInspector(self):
		self.webView.page().hideInspector()

	# 搜索文本
	@pyqtSlot(str, result = bool)
	def findText(self, text):
		return self.webView.page().findText(text)

	# 设置窗口图标
	@pyqtSlot(str)
	def setIcon(self, icon):
		if isinstance(icon, str):
			icon = QIcon(self.api.normUrl(icon))
		self.setWindowIcon(icon)

	# 设置内容是否已被修改(标题中需要有[*]标志)
	@pyqtSlot(bool)
	def setModified(self, modified):
		self.setWindowModified(modified)

	# 获取内容是否已被修改
	@pyqtSlot(result = bool)
	def isModified(self):
		return self.isWindowModified()

	# 设置是否模态
	@pyqtSlot(bool)
	def setModal(self, modal):
		super(Window, self).setModal(modal)

	# 获取是否模态
	@pyqtSlot(result = bool)
	def isModal(self):
		return super(Window, self).isModal()

	# 设置是否在任务栏中显示
	@pyqtSlot(bool)
	def setShowInTaskbar(self, showInTaskbar):
		if showInTaskbar:
			self.setWindowFlags(self.windowFlags() & ~ Qt.Tool)
		else:
			self.setWindowFlags(self.windowFlags() | Qt.Tool)

	# 获取是否在任务栏中显示
	@pyqtSlot(result = bool)
	def isShowInTaskbar(self):
		return self.testWindowFlags(Qt.Tool)

	# 设置窗口是否置顶
	@pyqtSlot(bool)
	def setStaysOnTop(self, staysOnTop):
		if staysOnTop:
			self.setWindowFlags(self.windowFlags() | Qt.WindowStaysOnTopHint)
		else:
			self.setWindowFlags(self.windowFlags() & ~ Qt.WindowStaysOnTopHint)

	# 获取窗口是否置顶
	@pyqtSlot(result = bool)
	def isStaysOnTop(self):
		return self.testWindowFlags(Qt.WindowStaysOnTopHint)

	# 设置是否显示系统边框
	@pyqtSlot(bool)
	def setFrameless(self, frameless):
		if frameless:
			self.setWindowFlags(self.windowFlags() & ~ Qt.CustomizeWindowHint & ~ Qt.WindowTitleHint | Qt.FramelessWindowHint)
		else:
			self.setWindowFlags(self.windowFlags() & ~ Qt.FramelessWindowHint | Qt.CustomizeWindowHint | Qt.WindowTitleHint)

	# 获取是否显示系统边框
	@pyqtSlot(result = bool)
	def isFrameless(self):
		return self.testWindowFlags(Qt.FramelessWindowHint)

	# 设置是否背景透明
	@pyqtSlot(bool)
	def setTransBackground(self, transBackground):
		palette = self.palette()
		if transBackground:
			palette.setBrush(QPalette.Base, Qt.transparent)
		else:
			palette.setBrush(QPalette.Base, Qt.white)
		self.setPalette(palette)

	# 获取是否背景透明
	@pyqtSlot(result = bool)
	def isTransBackground(self):
		palette = self.palette()
		return palette.brush(QPalette.Base) == Qt.transparent

	# 设置是否鼠标事件穿透
	@pyqtSlot(bool)
	def setTransMouseEvent(self, transMouseEvent):
		self.setAttribute(Qt.WA_TransparentForMouseEvents, transMouseEvent)
		self.setWindowFlags(self.windowFlags() | Qt.WindowTitleHint)

	# 获取是否是否鼠标事件穿透
	@pyqtSlot(result = bool)
	def isTransMouseEvent(self):
		return self.testAttribute(Qt.WA_TransparentForMouseEvents)

	# 设置窗口不透明度
	@pyqtSlot(float)
	def setOpacity(self, opacity):
		self.setWindowOpacity(opacity)

	# 获取窗口不透明度
	@pyqtSlot(result = float)
	def getOpacity(self):
		return self.windowOpacity()

	# 设置尺寸是否可调整
	@pyqtSlot(bool)
	def setResizable(self, resizable):
		if resizable:
			self.setMinimumSize(5, 5)
			self.setMaximumSize(0xFFFFFF, 0xFFFFFF)
		else:
			self.setFixedSize(self.width(), self.height())

	# 获取尺寸是否可调整
	@pyqtSlot(result = bool)
	def isResizable(self):
		return self.minimumSize() != self.maximumSize()

	# 设置宽度是否可调整
	@pyqtSlot(bool)
	def setResizableX(self, resizableX):
		if resizableX:
			self.setMinimumWidth(5)
			self.setMaximumWidth(0xFFFFFF)
		else:
			self.setFixedWidth(self.width())

	# 获取宽度是否可调整
	@pyqtSlot(result = bool)
	def isResizableX(self):
		return self.minimumWidth() != self.maximumWidth()

	# 设置高度是否可调整
	@pyqtSlot(bool)
	def setResizableY(self, resizableY):
		if resizableY:
			self.setMinimumHeight(5)
			self.setMaximumHeight(0xFFFFFF)
		else:
			self.setFixedHeight(self.height())

	# 获取高度是否可调整
	@pyqtSlot(result = bool)
	def isResizableY(self):
		return self.minimumHeight() != self.maximumHeight()

	# 设置是否可最小化
	@pyqtSlot(bool)
	def setMinimizable(self, minimizable):
		if minimizable:
			self.setWindowFlags(self.windowFlags() | Qt.WindowMinimizeButtonHint)
		else:
			self.setWindowFlags(self.windowFlags() & ~ Qt.WindowMinimizeButtonHint)

	# 获取是否可最小化
	@pyqtSlot(result = bool)
	def isMinimizable(self):
		return self.testWindowFlags(Qt.WindowMinimizeButtonHint)

	# 设置是否可最大化
	@pyqtSlot(bool)
	def setMaximizable(self, maximizable):
		if maximizable:
			self.setWindowFlags(self.windowFlags() | Qt.WindowMaximizeButtonHint)
		else:
			self.setWindowFlags(self.windowFlags() & ~ Qt.WindowMaximizeButtonHint)

	# 获取是否可最大化
	@pyqtSlot(result = bool)
	def isMaximizable(self):
		return self.testWindowFlags(Qt.WindowMaximizeButtonHint)

	# 设置是否可关闭
	@pyqtSlot(bool)
	def setClosable(self, closable):
		if closable:
			self.setWindowFlags(self.windowFlags() | Qt.WindowCloseButtonHint)
		else:
			self.setWindowFlags(self.windowFlags() & ~ Qt.WindowCloseButtonHint)

	# 获取是否可关闭
	@pyqtSlot(result = bool)
	def isClosable(self):
		return self.testWindowFlags(Qt.WindowCloseButtonHint)

	# 获取是否已最小化
	@pyqtSlot(result = bool)
	def isMinimized(self):
		return super(Window, self).isMinimized()

	# 获取是否已最大化
	@pyqtSlot(result = bool)
	def isMaximized(self):
		return super(Window, self).isMaximized()

	# 获取是否已最大化
	@pyqtSlot(result = bool)
	def isFullScreen(self):
		return super(Window, self).isFullScreen()

	# 最小化
	@pyqtSlot()
	def minimize(self):
		if self.isMinimizable():
			self.showMinimized()

	# 还原
	@pyqtSlot()
	def normalize(self):
		self.showNormal()

	# 最大化
	@pyqtSlot()
	def maximize(self):
		if self.isMaximizable():
			self.showMaximized()

	# 全屏
	@pyqtSlot()
	def showFullScreen(self):
		super(Window, self).showFullScreen()

	# 设置窗口坐标
	@pyqtSlot(int, int)
	def setPos(self, x, y):
		self.move(x, y)

	# 设置窗口尺寸
	@pyqtSlot(int, int)
	def setSize(self, width, height):
		self.resize(width, height)

	# 设置窗口最小尺寸
	@pyqtSlot(int, int)
	def setMinSize(self, width, height):
		self.setMinimumSize(width, height)

	# 设置窗口最大尺寸
	@pyqtSlot(int, int)
	def setMaxSize(self, width, height):
		self.setMaximumSize(width, height)

	# 设置尺寸控制大小
	@pyqtSlot(int)
	def setResizerSize(self, size):
		self.dragParams['size'] = size

	# 获取尺寸控制大小
	@pyqtSlot(result = int)
	def getResizerSize(self):
		return self.dragParams['size']

	# 设置尺寸控制边距
	@pyqtSlot(int)
	def setResizerMargin(self, margin):
		self.dragParams['margin'] = margin

	# 获取尺寸控制边距
	@pyqtSlot(result = int)
	def getResizerMargin(self):
		return self.dragParams['margin']

	# 是否正在拖动
	@pyqtSlot(result = bool)
	def isDraging(self):
		return self.dragParams['draging']

	# 开始拖动
	@pyqtSlot()
	def dragStart(self):
		self.dragParams['draging'] = True

	# 结束拖动
	@pyqtSlot()
	def dragStop(self):
		self.dragParams['type'] = Window.Move
		self.dragParams['draging'] = False

	# 窗口获取焦点
	@pyqtSlot()
	def activate(self):
		self.activateWindow()

	# 窗口是否已获得焦点
	@pyqtSlot(result = bool)
	def isActive(self):
		return self.isActiveWindow()

	# 设置窗口可用状态
	@pyqtSlot(bool)
	def setEnabled(self, enabled):
		super(Window, self).setEnabled(enabled)

	# 窗口是否可用
	@pyqtSlot(result = bool)
	def isEnabled(self):
		return super(Window, self).isEnabled()

	# 设置窗口可见状态
	@pyqtSlot(result = bool)
	def setVisible(self, visible):
		super(Window, self).setVisible(visible)

	# 窗口是否显示
	@pyqtSlot(result = bool)
	def isVisible(self):
		return super(Window, self).isVisible()

	# 显示窗口
	@pyqtSlot()
	def show(self):
		super(Window, self).show()

	# 隐藏窗口
	@pyqtSlot()
	def hide(self):
		super(Window, self).hide()

	# 关闭窗口
	@pyqtSlot()
	def close(self):
		super(Window, self).close()

	# Events
	def keyPressEvent(self, event):
		if(event.key() == Qt.Key_Escape):
			event.ignore()

	def mousePressEvent(self, event):
		self.dragParams['x'] = event.x()
		self.dragParams['y'] = event.y()
		self.dragParams['globalX'] = event.globalX()
		self.dragParams['globalY'] = event.globalY()
		self.dragParams['width'] = self.width()
		self.dragParams['height'] = self.height()
		if self.dragParams['type'] != Window.Move and self.isFrameless() and not self.isMaximized() and not self.isFullScreen():
			self.dragStart()

	def mouseReleaseEvent(self, event):
		self.dragStop()

	def mouseMoveEvent(self, event):

		if self.isFrameless() and not self.isMaximized() and not self.isFullScreen():
			# 判断鼠标类型
			cursorType = self.dragParams['type']
			if not self.dragParams['draging']:
				cursorType = self.dragParams['type'] = self.getCursorType(event.x(), event.y())

			# 设置鼠标形状
			if cursorType in (Window.ResizeTop, Window.ResizeBottom):
				self.webView.setCursor(Qt.SizeVerCursor)
			elif cursorType in (Window.ResizeLeft, Window.ResizeRight):
				self.webView.setCursor(Qt.SizeHorCursor)
			elif cursorType in (Window.ResizeTop | Window.ResizeRight, Window.ResizeLeft | Window.ResizeBottom):
				self.webView.setCursor(Qt.SizeBDiagCursor)
			elif cursorType in (Window.ResizeTop | Window.ResizeLeft, Window.ResizeRight | Window.ResizeBottom):
				self.webView.setCursor(Qt.SizeFDiagCursor)
			elif self.dragParams['draging']:
				self.webView.setCursor(Qt.ArrowCursor)

		# 判断窗口拖动
		dragType = self.dragParams['type']
		if self.dragParams['draging'] and not self.isMaximized() and not self.isFullScreen():
			x = self.x()
			y = self.y()
			width = self.width()
			height = self.height()
			if dragType == Window.Move:
				x = event.globalX() - self.dragParams['x']
				y = event.globalY() - self.dragParams['y']
			elif self.isFrameless():
				if dragType & Window.ResizeTop == Window.ResizeTop:
					y = event.globalY() - self.dragParams['margin']
					height = self.dragParams['height'] + self.dragParams['globalY'] - event.globalY()
				elif dragType & Window.ResizeBottom == Window.ResizeBottom:
					height = self.dragParams['height'] - self.dragParams['globalY'] + event.globalY()
				if dragType & Window.ResizeLeft == Window.ResizeLeft:
					x = event.globalX() - self.dragParams['margin']
					width = self.dragParams['width'] + self.dragParams['globalX'] - event.globalX()
				elif dragType & Window.ResizeRight == Window.ResizeRight:
					width = self.dragParams['width'] - self.dragParams['globalX'] + event.globalX()
			else:
				return

			if width < self.minimumWidth():
				width = self.minimumWidth()
			elif width > self.maximumWidth():
				width = self.maximumWidth()
			if height < self.minimumHeight():
				height = self.minimumHeight()
			elif height > self.maximumHeight():
				height = self.maximumHeight()

			self.setGeometry(x, y, width, height)

	def changeEvent(self, event):
		if event.type() == QEvent.ActivationChange:
			if self.isActiveWindow():
				self.onfocus.emit()
			else:
				self.onblur.emit()
		elif event.type() == QEvent.WindowStateChange:
			self.onstatechange.emit()

	def resizeEvent(self, event):
		size = event.size()
		oldSize = event.oldSize()
		self.onresize.emit(size.width(), size.height(), oldSize.width(), oldSize.height())
		self.webView.resize(super(Window, self).size())

	def moveEvent(self, event):
		pos = event.pos()
		oldPos = event.oldPos()
		self.onmove.emit(pos.x(), pos.y(), oldPos.x(), oldPos.y())

	def enterEvent(self, event):
		self.onmouseenter.emit()

	def leaveEvent(self, event):
		self.onmouseleave.emit()

	def showEvent(self, event):
		self.onshow.emit()

	def hideEvent(self, event):
		self.onhide.emit()

	def closeEvent(self, event):
		self.onclose.emit()
		if self.isClosable():
			self.webView.close()
			assets.windows = [i for i in assets.windows if i != self]
			event.accept()
		else:
			event.ignore()