import inspect

from scc.actions import *
from scc.constants import HIPFIRE_SENSIBLE
from scc.uinput import Axes, Keys, Rels

from . import _parses_as_itself, parser


class TestActions:

	def test_tests(self):
		"""
		Tests if this class has test for every Action defined in acitons.py.
		"""
		for cls in Action.ALL.values():
			if "/actions.py" in inspect.getfile(cls):
				if HatAction in cls.__bases__ or cls in (NoAction,) :
					# Skip over some hard-coded cases, these have
					# tests merged together under weird names
					continue
				method_name = "test_%s" % (cls.COMMAND,)
				assert hasattr(self, method_name), \
					"There is no test for %s" % (cls.COMMAND)

	def test_none(self):
		"""
		Tests if everything what should parse as NoAction parses as NoAction.
		"""
		assert not parser.restart("None").parse()
		assert not parser.restart("None()").parse()


	def test_axis(self):
		"""
		Tests if AxisAction can be converted to string and parsed back to
		same action.
		"""
		# With no optional parameters
		assert _parses_as_itself(AxisAction(Axes.ABS_X))
		# With min and max set
		assert _parses_as_itself(AxisAction(Axes.ABS_X, -10, 10.0))


	def test_raxis(self):
		"""
		Tests if RAxisAction can be converted to string and parsed back to
		same action.
		"""
		# With no optional parameters
		assert _parses_as_itself(RAxisAction(Axes.ABS_X))
		# With min and max set
		assert _parses_as_itself(RAxisAction(Axes.ABS_X, -10, 10.0))


	def test_hats(self):
		"""
		Tests if every Hat* actions can be converted to string and parsed back to
		same action.
		"""
		assert _parses_as_itself(HatUpAction(Axes.ABS_X))
		assert _parses_as_itself(HatDownAction(Axes.ABS_X))
		assert _parses_as_itself(HatLeftAction(Axes.ABS_X))
		assert _parses_as_itself(HatRightAction(Axes.ABS_X))


	def test_mouse(self):
		"""
		Tests if MouseAction can be converted to string and parsed back to
		same action.
		"""
		# With axis specified
		assert _parses_as_itself(MouseAction(Rels.REL_WHEEL))
		# Without axis (when used as trackbal)
		assert _parses_as_itself(MouseAction())


	def test_mouseabs(self):
		"""
		Tests if MouseAbsAction can be converted to string and parsed back to
		same action.
		"""
		# With axis specified
		assert _parses_as_itself(MouseAbsAction(Rels.REL_X))
		# Without axis (when used on pad directly)
		assert _parses_as_itself(MouseAbsAction())


	def test_area(self):
		"""
		Tests if AreaAction can be converted to string and
		parsed back to same action.
		"""
		assert _parses_as_itself(AreaAction(10, 10, 50, 50))


	def test_relarea(self):
		"""
		Tests if RelAreaAction can be converted to string
		and parsed back to same action.
		"""
		assert _parses_as_itself(RelAreaAction(10, 10, 50, 50))


	def test_winarea(self):
		"""
		Tests if WinAreaAction can be converted to string
		and parsed back to same action.
		"""
		assert _parses_as_itself(WinAreaAction(10, 10, 50, 50))


	def test_relwinarea(self):
		"""
		Tests if RelWinAreaAction can be converted to
		string and parsed back to same action.
		"""
		assert _parses_as_itself(RelWinAreaAction(10, 10, 50, 50))


	def test_gyro(self):
		"""
		Tests if GyroAction can be converted to string and
		parsed back to same action.
		"""
		# With one, two and three axes set
		assert _parses_as_itself(GyroAction(Axes.ABS_X))
		assert _parses_as_itself(GyroAction(Axes.ABS_X, Axes.ABS_Y))
		assert _parses_as_itself(GyroAction(Axes.ABS_X, Axes.ABS_Y, Axes.ABS_Z))


	def test_gyroabs(self):
		"""
		Tests if GyroAbsAction can be converted to string and
		parsed back to same action.
		"""
		assert _parses_as_itself(GyroAbsAction(Axes.ABS_X))
		assert _parses_as_itself(GyroAbsAction(Axes.ABS_X, Axes.ABS_Y))
		assert _parses_as_itself(GyroAbsAction(Axes.ABS_X, Axes.ABS_Y, Axes.ABS_Z))


	def test_resetgyro(self):
		"""
		Tests if ResetGyroAction can be converted to string and
		parsed back to same action.
		"""
		assert _parses_as_itself(ResetGyroAction())


	def test_tilt(self):
		"""
		Tests if TiltAction can be converted to string and
		parsed back to same action.
		"""
		# With only one button
		assert _parses_as_itself(TiltAction( ButtonAction(Keys.KEY_D) ))
		# With all buttons
		assert _parses_as_itself(TiltAction(
			ButtonAction(Keys.KEY_D), ButtonAction(Keys.KEY_U),
			ButtonAction(Keys.KEY_L), ButtonAction(Keys.KEY_R)
		))


	def test_trackball(self):
		"""
		Tests if TrackballAction can be converted to string and parsed
		back to same action.
		"""
		assert _parses_as_itself(TrackballAction())


	def test_button(self):
		"""
		Tests if ButtonAction can be converted to string and parsed back to
		same action.
		"""
		# Simple
		assert _parses_as_itself(ButtonAction(Keys.BTN_LEFT))
		# Two buttons
		assert _parses_as_itself(ButtonAction(Keys.BTN_LEFT, Keys.BTN_RIGHT))
		# With one trigger setting
		assert _parses_as_itself(ButtonAction(Keys.BTN_LEFT, Keys.BTN_RIGHT, 10))
		# With two trigger settings
		assert _parses_as_itself(ButtonAction(Keys.BTN_LEFT, Keys.BTN_RIGHT, 10, 90))


	def test_multiaction(self):
		"""
		Tests if MultiAction can be converted to string and parsed back to
		same action.
		"""
		assert _parses_as_itself(MultiAction(
			ButtonAction(Keys.BTN_LEFT),
			ButtonAction(Keys.BTN_RIGHT),
			ButtonAction(Keys.BTN_MIDDLE)
		))


	def test_dpad(self):
		"""
		Tests if DPadAction can be converted to string and
		parsed back to same action.
		"""
		# Default diagonal rage
		assert _parses_as_itself(DPadAction(
			ButtonAction(Keys.BTN_LEFT),
			ButtonAction(Keys.BTN_RIGHT),
			ButtonAction(Keys.BTN_MIDDLE),
			ButtonAction(Keys.KEY_A)
		))
		# Modified diagonal rage
		assert _parses_as_itself(DPadAction(33,
			ButtonAction(Keys.BTN_RIGHT),
			ButtonAction(Keys.KEY_A),
			ButtonAction(Keys.BTN_LEFT),
			ButtonAction(Keys.BTN_MIDDLE),
		))


	def test_ring(self):
		"""
		Tests if DPadAction can be converted to string and
		parsed back to same action.
		"""
		assert _parses_as_itself(RingAction(0.1,
			DPadAction(
				ButtonAction(Keys.BTN_LEFT),
				ButtonAction(Keys.BTN_RIGHT),
				ButtonAction(Keys.BTN_MIDDLE),
				ButtonAction(Keys.KEY_A)
			),
			XYAction(
				AxisAction(Axes.ABS_X),
				AxisAction(Axes.ABS_Y)
			)
		))


	def test_dpad8(self):
		"""
		Tests if DPad8Action can be converted to string and
		parsed back to same action.
		"""
		# Default diagonal rage
		assert _parses_as_itself(DPad8Action(
			ButtonAction(Keys.BTN_LEFT),
			ButtonAction(Keys.BTN_RIGHT),
			ButtonAction(Keys.BTN_MIDDLE),
			ButtonAction(Keys.KEY_A),
			ButtonAction(Keys.KEY_B),
			ButtonAction(Keys.KEY_C),
			ButtonAction(Keys.KEY_D),
			ButtonAction(Keys.KEY_E)
		))
		# Modified diagonal rage
		assert _parses_as_itself(DPad8Action(61,
			ButtonAction(Keys.BTN_RIGHT),
			ButtonAction(Keys.KEY_C),
			ButtonAction(Keys.KEY_A),
			ButtonAction(Keys.BTN_LEFT),
			ButtonAction(Keys.KEY_E),
			ButtonAction(Keys.KEY_B),
			ButtonAction(Keys.KEY_D),
			ButtonAction(Keys.BTN_MIDDLE),
		))


	def test_XY(self):
		"""
		Tests if XYAciton can be converted to string and parsed back to
		same action.
		"""
		assert _parses_as_itself(XYAction(
			AxisAction(Axes.ABS_X),
			AxisAction(Axes.ABS_Y)
		))


	def test_relXY(self):
		"""
		Tests if relXYAciton can be converted to string and parsed back to
		same action.
		"""
		assert _parses_as_itself(RelXYAction(
			AxisAction(Axes.ABS_RX),
			AxisAction(Axes.ABS_RY)
		))


	def test_trigger(self):
		"""
		Tests if TriggerAction can be converted to string and parsed back to
		same action.
		"""
		assert _parses_as_itself(TriggerAction(
			15, 234,
			ButtonAction(Keys.KEY_A)
		))

	def test_hipfire(self):
		"""
		Tests if HipfireAction can be converted to string and parsed back to
		same action.
		"""
		a = ButtonAction(Keys.KEY_A)
		b = ButtonAction(Keys.KEY_B)
		assert _parses_as_itself(HipfireAction(a, b))
		assert _parses_as_itself(HipfireAction(49, 253, a, b))
		assert _parses_as_itself(HipfireAction(a, b, HIPFIRE_SENSIBLE))
		assert _parses_as_itself(HipfireAction(a, b, HIPFIRE_SENSIBLE, 0.14))
		assert _parses_as_itself(HipfireAction(49, a, b, HIPFIRE_SENSIBLE, 0.14))
		assert _parses_as_itself(HipfireAction(49, 253, a, b, HIPFIRE_SENSIBLE, 0.14))
