# Shows a floating window when authenticating
import cairo
import gi
import signal
import sys
import paths_factory
import os

from i18n import _

# Make sure we have the libs we need
gi.require_version("Gtk", "3.0")
gi.require_version("Gdk", "3.0")

# Import them
from gi.repository import Gtk as gtk
from gi.repository import Gdk as gdk
from gi.repository import GObject as gobject

# Set window size constants
windowWidth = 400
windowHeight = 100


class StickyWindow(gtk.Window):
	# Set default messages to show in the popup
	message = _("Loading...  ")
	subtext = ""

	def __init__(self):
		"""Initialize the sticky window"""
		# Make the class a GTK window
		gtk.Window.__init__(self)

		# Get the absolute or relative path to the logo file
		logo_path = paths_factory.logo_path()

		# Create image and calculate scale size based on image size
		self.logo_surface = cairo.ImageSurface.create_from_png(logo_path)
		self.logo_ratio = float(windowHeight - 20) / float(self.logo_surface.get_height())

		# Set the title of the window
		self.set_title(_("Howdy Authentication"))

		# Set a bunch of options to make the window stick and be on top of everything
		self.stick()
		self.set_gravity(gdk.Gravity.STATIC)
		self.set_resizable(False)
		self.set_keep_above(True)
		self.set_app_paintable(True)
		self.set_skip_pager_hint(True)
		self.set_skip_taskbar_hint(True)
		self.set_can_focus(False)
		self.set_can_default(False)
		self.set_focus(None)
		self.set_type_hint(gdk.WindowTypeHint.NOTIFICATION)
		self.set_decorated(False)

		# Listen for a window redraw
		self.connect("draw", self.draw)
		# Listen for a force close or click event and exit
		self.connect("destroy", self.exit)
		self.connect("delete_event", self.exit)
		self.connect("button-press-event", self.exit)
		self.connect("button-release-event", self.exit)

		# Create a GDK drawing, restricts the window size
		darea = gtk.DrawingArea()
		darea.set_size_request(windowWidth, windowHeight)
		self.add(darea)

		# Get the default screen
		screen = gdk.Screen.get_default()
		visual = screen.get_rgba_visual()
		self.set_visual(visual)

		# Move the window to the center top of the default window, where a webcam usually is
		self.move((screen.get_width() / 2) - (windowWidth / 2), 0)

		# Show window and force a resize again
		self.show_all()
		self.resize(windowWidth, windowHeight)

		# Add a timeout to catch input passed from compare.py
		gobject.timeout_add(100, self.catch_stdin)

		# Start GTK main loop
		gtk.main()

	def draw(self, widget, ctx):
		"""Draw the UI"""
		# Change cursor to the kill icon
		self.get_window().set_cursor(gdk.Cursor(gdk.CursorType.PIRATE))

		# Draw a semi transparent background
		ctx.set_source_rgba(0, 0, 0, .7)
		ctx.set_operator(cairo.OPERATOR_SOURCE)
		ctx.paint()
		ctx.set_operator(cairo.OPERATOR_OVER)

		# Position and draw the logo
		ctx.translate(15, 10)
		ctx.scale(self.logo_ratio, self.logo_ratio)
		ctx.set_source_surface(self.logo_surface)
		ctx.paint()

		# Calculate main message positioning, as the text is higher if there's a subtext
		if self.subtext:
			ctx.move_to(380, 145)
		else:
			ctx.move_to(380, 175)

		# Draw the main message
		ctx.set_source_rgba(255, 255, 255, .9)
		ctx.set_font_size(80)
		ctx.select_font_face("Arial", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
		ctx.show_text(self.message)

		# Draw the subtext if there is one
		if self.subtext:
			ctx.move_to(380, 210)
			ctx.set_source_rgba(230, 230, 230, .8)
			ctx.set_font_size(40)
			ctx.select_font_face("Arial", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_NORMAL)
			ctx.show_text(self.subtext)

	def catch_stdin(self):
		"""Catch input from stdin and redraw"""
		# Wait for a line on stdin
		comm = sys.stdin.readline()[:-1]

		# If the line is not empty
		if comm:
			# Parse a message
			if comm[0] == "M":
				self.message = comm[2:].strip()
			# Parse subtext
			if comm[0] == "S":
				# self.subtext += " "
				self.subtext = comm[2:].strip()

		# Redraw the ui
		self.queue_draw()

		# Fire this function again in 10ms, as we're waiting on IO in readline anyway
		gobject.timeout_add(10, self.catch_stdin)

	def exit(self, widget, context):
		"""Cleanly exit"""
		gtk.main_quit()
		return True


# Make sure we quit on a SIGINT
signal.signal(signal.SIGINT, signal.SIG_DFL)

# Open the GTK window
window = StickyWindow()
