# -*- coding: utf-8 -*-
from kivy.properties import ListProperty, NumericProperty, StringProperty, \
	BooleanProperty
from kivy.animation import Animation
from kivy.graphics import Color, Ellipse, StencilPush, StencilPop, \
	StencilUse, StencilUnUse, Rectangle


class CommonRipple(object):
	ripple_rad = NumericProperty()
	ripple_rad_default = NumericProperty(1)
	ripple_post = ListProperty()
	ripple_color = ListProperty()
	ripple_alpha = NumericProperty(.5)
	ripple_scale = NumericProperty(None)
	ripple_duration_in_fast = NumericProperty(.3)
	# FIXME: These speeds should be calculated based on widget size in dp
	ripple_duration_in_slow = NumericProperty(2)
	ripple_duration_out = NumericProperty(.3)
	ripple_func_in = StringProperty('out_quad')
	ripple_func_out = StringProperty('out_quad')

	doing_ripple = BooleanProperty(False)
	finishing_ripple = BooleanProperty(False)
	fading_out = BooleanProperty(False)

	def on_touch_down(self, touch):
		if touch.is_mouse_scrolling:
			return False
		if not self.collide_point(touch.x, touch.y):
			return False

		if not self.disabled:
			if self.doing_ripple:
				Animation.cancel_all(self, 'ripple_rad', 'ripple_color',
									 'rect_color')
				self.anim_complete()
			self.ripple_rad = self.ripple_rad_default
			self.ripple_pos = (touch.x, touch.y)

			if self.ripple_color != []:
				pass
			elif hasattr(self, 'theme_cls'):
				self.ripple_color = self.theme_cls.ripple_color
			else:
				# If no theme, set Grey 300
				self.ripple_color = [0.8784313725490196, 0.8784313725490196,
									 0.8784313725490196, self.ripple_alpha]
			self.ripple_color[3] = self.ripple_alpha

			self.lay_canvas_instructions()
			self.finish_rad = max(self.width, self.height) * self.ripple_scale
			self.start_ripple()
		return super(CommonRipple, self).on_touch_down(touch)

	def lay_canvas_instructions(self):
		raise NotImplementedError

	def on_touch_move(self, touch, *args):
		if not self.collide_point(touch.x, touch.y):
			if not self.finishing_ripple and self.doing_ripple:
				self.finish_ripple()
		return super(CommonRipple, self).on_touch_move(touch, *args)

	def on_touch_up(self, touch):
		if self.collide_point(touch.x, touch.y) and self.doing_ripple:
			self.finish_ripple()
		return super(CommonRipple, self).on_touch_up(touch)

	def start_ripple(self):
		if not self.doing_ripple:
			anim = Animation(
				ripple_rad=self.finish_rad,
				t='linear',
				duration=self.ripple_duration_in_slow)
			anim.bind(on_complete=self.fade_out)
			self.doing_ripple = True
			anim.start(self)

	def _set_ellipse(self, instance, value):
		self.ellipse.size = (self.ripple_rad, self.ripple_rad)

	# Adjust ellipse pos here

	def _set_color(self, instance, value):
		self.col_instruction.a = value[3]

	def finish_ripple(self):
		if self.doing_ripple and not self.finishing_ripple:
			Animation.cancel_all(self, 'ripple_rad')
			anim = Animation(ripple_rad=self.finish_rad,
							 t=self.ripple_func_in,
							 duration=self.ripple_duration_in_fast)
			anim.bind(on_complete=self.fade_out)
			self.finishing_ripple = True
			anim.start(self)

	def fade_out(self, *args):
		rc = self.ripple_color
		if not self.fading_out:
			Animation.cancel_all(self, 'ripple_color')
			anim = Animation(ripple_color=[rc[0], rc[1], rc[2], 0.],
							 t=self.ripple_func_out,
							 duration=self.ripple_duration_out)
			anim.bind(on_complete=self.anim_complete)
			self.fading_out = True
			anim.start(self)

	def anim_complete(self, *args):
		self.doing_ripple = False
		self.finishing_ripple = False
		self.fading_out = False
		self.canvas.after.clear()


class RectangularRippleBehavior(CommonRipple):
	ripple_scale = NumericProperty(2.75)

	def lay_canvas_instructions(self):
		with self.canvas.after:
			StencilPush()
			Rectangle(pos=self.pos, size=self.size)
			StencilUse()
			self.col_instruction = Color(rgba=self.ripple_color)
			self.ellipse = \
				Ellipse(size=(self.ripple_rad, self.ripple_rad),
						pos=(self.ripple_pos[0] - self.ripple_rad / 2.,
							 self.ripple_pos[1] - self.ripple_rad / 2.))
			StencilUnUse()
			Rectangle(pos=self.pos, size=self.size)
			StencilPop()
		self.bind(ripple_color=self._set_color,
				  ripple_rad=self._set_ellipse)

	def _set_ellipse(self, instance, value):
		super(RectangularRippleBehavior, self)._set_ellipse(instance, value)
		self.ellipse.pos = (self.ripple_pos[0] - self.ripple_rad / 2.,
							self.ripple_pos[1] - self.ripple_rad / 2.)


class CircularRippleBehavior(CommonRipple):
	ripple_scale = NumericProperty(1)

	def lay_canvas_instructions(self):
		with self.canvas.after:
			StencilPush()
			self.stencil = Ellipse(size=(self.width * self.ripple_scale,
										 self.height * self.ripple_scale),
								   pos=(self.center_x - (self.width * self.ripple_scale) / 2,
										self.center_y - (self.height * self.ripple_scale) / 2))
			StencilUse()
			self.col_instruction = Color(rgba=self.ripple_color)
			self.ellipse = Ellipse(size=(self.ripple_rad, self.ripple_rad),
								   pos=(self.center_x - self.ripple_rad / 2.,
										self.center_y - self.ripple_rad / 2.))
			StencilUnUse()
			Ellipse(pos=self.pos, size=self.size)
			StencilPop()
			self.bind(ripple_color=self._set_color,
					  ripple_rad=self._set_ellipse)

	def _set_ellipse(self, instance, value):
		super(CircularRippleBehavior, self)._set_ellipse(instance, value)
		if self.ellipse.size[0] > self.width * .6 and not self.fading_out:
			self.fade_out()
		self.ellipse.pos = (self.center_x - self.ripple_rad / 2.,
							self.center_y - self.ripple_rad / 2.)
