#!/usr/bin/python3
# -*- coding: utf-8 -*-
# ******************************************************************************
# ZYNTHIAN PROJECT: Zynthian Control Device Driver
#
# Zynthian Control Device Driver for "OpenDesk Raspberry Pico"
#
# Copyright (C) 2024 Fernando Moyano <jofemodo@zynthian.org>
# Copyright (C) 2024 Christopher Matthews <c.matthews@freenet.de>
#
# ******************************************************************************
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of
# the License, or any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# For a full copy of the GNU General Public License see the LICENSE.txt file.
#
# ******************************************************************************

import logging
from time import sleep

# Zynthian specific modules
from zyncoder.zyncore import lib_zyncore
from zyngine.zynthian_signal_manager import zynsigman
from zyngine.ctrldev.zynthian_ctrldev_base import zynthian_ctrldev_zynmixer

# --------------------------------------------------------------------------
# AKAI MPD26 Integration
# --------------------------------------------------------------------------


class zynthian_ctrldev_akai_mpd26(zynthian_ctrldev_zynmixer):

	dev_ids = ["Akai MPD26 IN 1"]
	midi_chan = 0x0
	sysex_answer_cb = None
	poti = None

	pads_ccnum = range(36, 52)
	faders_ccnum = [1, 2, 3, 4, 5, 6]  # 255 is Master slider

	# Function to initialise class
	def __init__(self, state_manager, idev_in, idev_out=None):
		self.midimix_bank = 0
		super().__init__(state_manager, idev_in, idev_out)

	def send_sysex(self, data):
		if self.idev_out is not None:
			msg = bytes.fromhex(f"F0 47 0{hex(self.midi_chan)[2:]} 78 10 04 59 {data} F7")
			lib_zyncore.dev_send_midi_event(self.idev_out, msg, len(msg))

	def init(self):
		super().init()

	def end(self):
		super().end()

	def update_mixer_strip(self, chan, symbol, value):
		if self.idev_out is None:
			return
		chain_id = self.chain_manager.get_chain_id_by_mixer_chan(chan)
		if chain_id:
			col = self.chain_manager.get_chain_index(chain_id)

	def get_mixer_chan_from_device_col(self, col):
		if self.midimix_bank:
			col += 8
		chain = self.chain_manager.get_chain_by_index(col)
		if chain:
			return chain.mixer_chan
		else:
			return None

	def update_mixer_active_chain(self, active_chain):
		pass

	def midi_event(self, ev):
		evtype = (ev[0] >> 4) & 0x0F
		if evtype == 0xB:
			ccnum = ev[1] & 0x7F
			ccval = ev[2] & 0x7F
			if ccnum in self.faders_ccnum:
				col = self.faders_ccnum.index(ccnum)
				mixer_chan = self.get_mixer_chan_from_device_col(col)
				if mixer_chan is not None:
					self.zynmixer.set_level(mixer_chan, ccval / 127.0, True)
				return True

			#  NRPN Section for the Encoders
			elif ccnum == 99:  # Get NRPN Encoder Value
				self.poti = ccval
			elif ccnum == 96 and ccval == 1:  # Get NRPN INC Value
				if self.poti == 3:	 # CTRL-1
					self.state_manager.send_cuia("ZYNPOT", params=[0, 1])
				elif self.poti == 1:  # CTRL-2
					self.state_manager.send_cuia("ZYNPOT", params=[1, 1])
				elif self.poti == 4:  # CTRL-3
					self.state_manager.send_cuia("ZYNPOT", params=[2, 1])
				elif self.poti == 2:  # CTRL-3
					self.state_manager.send_cuia("ZYNPOT", params=[3, 1])
				elif self.poti == 5:  # Customer LEFT/RIGHT
					self.state_manager.send_cuia("ARROW_RIGHT")
				elif self.poti == 6:  # Customer UP/DOWN
					self.state_manager.send_cuia("ARROW_DOWN")

			elif ccnum == 97 and ccval == 1:  # Get NRPN DEC Value
				if self.poti == 3:
					self.state_manager.send_cuia("ZYNPOT", params=[0, -1])
				elif self.poti == 1:  # CTRL-2
					self.state_manager.send_cuia("ZYNPOT", params=[1, -1])
				elif self.poti == 4:  # CTRL-3
					self.state_manager.send_cuia("ZYNPOT", params=[2, -1])
				elif self.poti == 2:  # CTRL-4
					self.state_manager.send_cuia("ZYNPOT", params=[3, -1])
				elif self.poti == 5:  # Customer LEFT/RIGHT
					self.state_manager.send_cuia("ARROW_LEFT")
				elif self.poti == 6:  # Customer UP/DOWN
					self.state_manager.send_cuia("ARROW_UP")

		# SysEx
		elif ev[0] == 0xF0:
			if callable(self.sysex_answer_cb):
				self.sysex_answer_cb(ev)
			else:
				logging.debug(f"Received SysEx (unprocessed) => {ev.hex(' ')}")
			return True

		# PADS
		elif evtype == 0x9:  # Capture NoteOn
			ccnum = ev[1] & 0x7F
			if ccnum in self.pads_ccnum:
				if self.pads_ccnum.index(ccnum) == 0:
					self.state_manager.send_cuia("ARROW_LEFT")
				elif self.pads_ccnum.index(ccnum) == 1:
					self.state_manager.send_cuia("ARROW_DOWN")
				elif self.pads_ccnum.index(ccnum) == 2:
					self.state_manager.send_cuia("ARROW_RIGHT")
				elif self.pads_ccnum.index(ccnum) == 5:
					self.state_manager.send_cuia("ARROW_UP")
				elif self.pads_ccnum.index(ccnum) == 3:
					self.state_manager.send_cuia("ZYNSWITCH", params=["0", "P"])
				elif self.pads_ccnum.index(ccnum) == 7:
					self.state_manager.send_cuia("ZYNSWITCH", params=["1", "P"])
				elif self.pads_ccnum.index(ccnum) == 11:
					self.state_manager.send_cuia("ZYNSWITCH", params=["2", "P"])
				elif self.pads_ccnum.index(ccnum) == 15:
					self.state_manager.send_cuia("ZYNSWITCH", params=["3", "P"])

		elif evtype == 0x8:  # Capture NoteOff
			ccnum = ev[1] & 0x7F
			if self.pads_ccnum.index(ccnum) == 3:
				self.state_manager.send_cuia("ZYNSWITCH", params=["0", "R"])
			elif self.pads_ccnum.index(ccnum) == 7:
				self.state_manager.send_cuia("ZYNSWITCH", params=["1", "R"])
			elif self.pads_ccnum.index(ccnum) == 11:
				self.state_manager.send_cuia("ZYNSWITCH", params=["2", "R"])
			elif self.pads_ccnum.index(ccnum) == 15:
				self.state_manager.send_cuia("ZYNSWITCH", params=["3", "R"])

		else:
			logging.debug(f"MY Debug: => {ev.hex(' ')}")

# ------------------------------------------------------------------------------
