import abc
from utils.value import AttributeChange
from contextlib import contextmanager


class AStirrer(AttributeChange):
	def __init__(self, dt):
		AttributeChange.__init__(self)
		self.dt = dt
		self.speed = 0
		self.cycleTime = 1
		self.dutyCycle = 1
		self.cycleCounter = 0
		self.isOn = 1

	def process(self):
		isOn = self.isOn
		self.cycleCounter += self.dt
		if self.cycleCounter >= self.cycleTime:
			self.cycleCounter -= self.cycleTime
			isOn = 0

		if self.cycleCounter >= (self.cycleTime * (1-self.dutyCycle)):
			if not isOn:
				isOn = 1

		if self.isOn != isOn:
			if isOn:
				self._on_set_speed(self.speed)
			else:
				self._on_set_speed(0)

		self.isOn = isOn
		self._on_process()

	def set_speed(self, speed):
		self.speed = speed
		if self.isOn or self.dutyCycle == 1:
			self._on_set_speed(speed)

	def set_cycle_time(self, time):
		self.cycleTime = time

	def set_duty_cycle(self, dutyCycle):
		self.dutyCycle = dutyCycle

	@abc.abstractmethod
	def get_speed(self):
		return None

	@abc.abstractmethod
	def _on_set_speed(self, speed):
		pass

	@abc.abstractmethod
	def _on_process(self):
		pass

	@contextmanager
	def open(self):
		try:
			self.activate(True)
			yield None
		finally:
			self.activate(False)

		return None

	@abc.abstractmethod
	def activate(self, enable):
		pass

	@abc.abstractmethod
	def is_activated(self):
		pass

