import uuid
from ableton.v2.base import liveobj_valid, clamp
from ableton.v2.control_surface.mode import ModesComponent, AddLayerMode, make_mode_button_control
from ableton.v2.control_surface.control import InputControl

class ExquisMode(AddLayerMode):
	"A mode that enables/disables its component in addition to adding/removing its layer"

	def enter_mode(self):
		self._get_component().set_enabled(True)
		if self._layer:
			self._layer.grab(self._get_component())

	def leave_mode(self):
		if self._layer:
			self._layer.release(self._get_component())
		self._get_component().set_enabled(False)

class ExquisModesComponent(ModesComponent):
	"A ModesComponent with Exquis-specific behavior"

	def __init__(self, *a, **k):
		super(ExquisModesComponent, self).__init__(*a, **k)
	
	def add_mode_button_control(self, mode_name, behaviour):
		kwargs = {}
		if hasattr(behaviour, "mode_selected_color"):
			kwargs["mode_selected_color"] = behaviour.mode_selected_color
		if hasattr(behaviour, "mode_unselected_color"):
			kwargs["mode_unselected_color"] = behaviour.mode_unselected_color
		button_control = make_mode_button_control(self, mode_name, behaviour, delay_time=0.2, **kwargs)
		self.add_control('%s_button' % mode_name, button_control)
		self._update_mode_buttons(self.selected_mode)

class SendValueMixin(object):
	"A mixin for controls that send their value to the control element"

	def __init__(self, initial_value, *a, **k):
		(super(SendValueMixin, self).__init__)(*a, **k)
		self._value = initial_value

	@property
	def value(self):
		return self._value

	@value.setter
	def value(self, value):
		if self._value != value:
			self._value = value
			self._send_current_value()

	def set_control_element(self, control_element):
		super(SendValueMixin, self).set_control_element(control_element)
		self._send_current_value()

	def update(self):
		super(SendValueMixin, self).update()
		self._send_current_value()

	def _send_current_value(self):
		if self._control_element:
			self._control_element.send_value(self._value)

class ValueControl(InputControl):
	"A control that sends its value to the control element"

	class State(SendValueMixin, InputControl.State):
		pass
	def __init__(self, *a, **k):
		(super(ValueControl, self).__init__)(extra_args=a, extra_kws=k)

def normalized_parameter_value(parameter, value=None):
	"Return the normalized value of a parameter"

	result = 0.0
	if liveobj_valid(parameter):
		value = value if value is not None else parameter.value
		param_range = parameter.max - parameter.min
		result = (value - parameter.min) / param_range
	return clamp(result, 0.0, 1.0)

def all_tracks(song):
	"Return all tracks in the song"

	return tuple(song.visible_tracks) + tuple(song.return_tracks) + (song.master_track,)

def track_id(track):
	"Return the unique id of a track, recording it if it doesn't have one"

	uid = track.get_data("exquis_unique_id", None)
	if uid is None:
		uid = str(uuid.uuid4())
		track.set_data("exquis_unique_id", uid)
	return uid
