# THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
# APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
# HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
# OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
# IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
# ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

# IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
# WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
# THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
# GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
# USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
# DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
# PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
# EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGES.

# Copyright (c) 2018 Dr. Oliver Barth <info@drb-electronic.de>
# Frame for controlling CAN module

import ttk
import Tkinter as tk
from can_MCP2515 import *
from drblayout import *
from drbTable import *

#
class FrameCAN():

	#
	def __init__(self, frmCAN, hwmng):
		self.can = hwmng.getCAN()
		self.can_rx_ids = [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1]
		
		# configure
		frmCAN.columnconfigure(0, weight=1)
		frmCANConfig = ttk.LabelFrame(frmCAN, text="config")
		frmCANConfig.grid(column=0, row=0, sticky="nsew", padx=DRBLAYOUT_CompPadding, pady=DRBLAYOUT_CompPadding)
		labCAN_Baud = ttk.Label(frmCANConfig, text="Baudrate", padding=DRBLAYOUT_CompPadding)
		labCAN_Baud.grid(column=0, row=0, sticky="ns", padx=DRBLAYOUT_CompPadding, pady=DRBLAYOUT_CompPadding)
		entryCAN_Baud = ttk.Entry(frmCANConfig, width=11)
		entryCAN_Baud.grid(column=1, row=0, sticky="ns", padx=DRBLAYOUT_CompPadding, pady=DRBLAYOUT_CompPadding)
		butSetBaud = ttk.Button(frmCANConfig, text='set', width=10, command=self.setCANBaudrate)
		butSetBaud.grid(column=2, row=0, sticky="ns", padx=DRBLAYOUT_CompPadding, pady=DRBLAYOUT_CompPadding)
		labCAN_Opmode = ttk.Label(frmCANConfig, text="Opmode", padding=DRBLAYOUT_CompPadding)
		labCAN_Opmode.grid(column=0, row=1, sticky="ns", padx=DRBLAYOUT_CompPadding, pady=DRBLAYOUT_CompPadding)
		self.comboCAN_Opmodes = ttk.Combobox(frmCANConfig, values=MCP2515_opmodes, width=10)
		self.comboCAN_Opmodes.grid(column=1, row=1, sticky="ns", padx=DRBLAYOUT_CompPadding, pady=DRBLAYOUT_CompPadding)
		butSetOpmode = ttk.Button(frmCANConfig, text='set', width=10, command=self.setCANOpmode)
		butSetOpmode.grid(column=2, row=1, sticky="ns", padx=DRBLAYOUT_CompPadding, pady=DRBLAYOUT_CompPadding)

		labCAN_Register = ttk.Label(frmCANConfig, text="Register", padding=DRBLAYOUT_CompPadding)
		labCAN_Register.grid(column=3, row=0, sticky="ns", padx=DRBLAYOUT_CompPadding, pady=DRBLAYOUT_CompPadding)
		self.comboCAN_Register = ttk.Combobox(frmCANConfig, values=sorted(MCP2515_regs.keys()), width=10)
		self.comboCAN_Register.grid(column=4, row=0, sticky="ns", padx=DRBLAYOUT_CompPadding, pady=DRBLAYOUT_CompPadding)
		self.tfCAN_Register = tk.Text(frmCANConfig, height=1, width=11)
		self.tfCAN_Register.grid(column=5, row=0, sticky="ns", padx=DRBLAYOUT_CompPadding, pady=DRBLAYOUT_CompPadding)
		butMCP2515RegsSet = ttk.Button(frmCANConfig, text='set', width=10, command=self.setCANReg)
		butMCP2515RegsSet.grid(column=6, row=0, sticky="ns", padx=DRBLAYOUT_CompPadding, pady=DRBLAYOUT_CompPadding)
		butMCP2515RegsGet = ttk.Button(frmCANConfig, text='get', width=10, command=self.getCANReg)
		butMCP2515RegsGet.grid(column=7, row=0, sticky="ns", padx=DRBLAYOUT_CompPadding, pady=DRBLAYOUT_CompPadding)

		# receive
		frmCANRx = ttk.LabelFrame(frmCAN, text="receive")
		frmCANRx.grid(column=0, row=1, sticky="nsew", padx=DRBLAYOUT_CompPadding, pady=DRBLAYOUT_CompPadding)
		self.posTableRxFrame = ttk.Frame(frmCANRx, relief=tk.SUNKEN)
		self.posTableRxFrame.grid(column=0, row=0, sticky="nsew", padx=1, pady=1)
		colWidth = [10, 10, 10, 10, 10, 10, 10, 10, 10, 10]
		colHeader = ['id', 'dlc', 'b1', 'b2', 'b3', 'b4', 'b5', 'b6', 'b7', 'b8']
		self.posTableRx = DrbTable(self.posTableRxFrame, "pos", 1, 10, colWidth, colHeader)
		for i in range (0, 10):
			row = ['', '', '', '', '', '', '', '', '', '']
			self.posTableRx.addRow(row)
		butCANRx_Clear = ttk.Button(frmCANRx, text='clear', command=self.clearRXCAN)
		butCANRx_Clear.grid(column=1, row=0, sticky='nsew', padx=DRBLAYOUT_CompPadding, pady=DRBLAYOUT_CompPadding)

		# transmit
		frmCANTx = ttk.LabelFrame(frmCAN, text="transmit")
		frmCANTx.grid(column=0, row=2, sticky="nsew", padx=DRBLAYOUT_CompPadding, pady=DRBLAYOUT_CompPadding)
		self.posTableTxFrame = ttk.Frame(frmCANTx, relief=tk.SUNKEN)
		self.posTableTxFrame.grid(column=0, row=0, sticky="nsew", padx=1, pady=1)
		colWidth = [10, 10, 10, 10, 10, 10, 10, 10, 10, 10]
		colHeader = ['id', 'dlc', 'b1', 'b2', 'b3', 'b4', 'b5', 'b6', 'b7', 'b8']
		self.posTableTx = DrbTable(self.posTableTxFrame, "pos", 1, 10, colWidth, colHeader)
		row = ['0x100', '8', '0x01', '0x02', '0x03', '0x04', '0x05', '0x06', '0x07', '0x08']
		self.posTableTx.addRow(row)
		for i in range (0, 9):
			row = ['', '', '', '', '', '', '', '', '', '']
			self.posTableTx.addRow(row)
		butCANTx = ttk.Button(frmCANTx, text='transmit', command=self.txCANMsg)
		butCANTx.grid(column=1, row=0, sticky='nsew', padx=DRBLAYOUT_CompPadding, pady=DRBLAYOUT_CompPadding)

		#
		entryCAN_Baud.insert(0, '500000')
		self.comboCAN_Opmodes.current(0)
		self.comboCAN_Register.current(0)

	#
	def setCANBaudrate(self):
		can_baud = entryCAN_Baud.get()
		self.can.setBaudrate(can_baud)

	#
	def setCANOpmode(self):
		pass
		#opmode = entryCAN_Baud.get()
		#self.can.setOpmode(opmode)

	#
	def getCANReg(self):
		reg = MCP2515_regs[self.comboCAN_Register.get()]
		val = self.can.getReg(reg)
		self.tfCAN_Register.delete("1.0", tk.END)
		self.tfCAN_Register.insert("1.0", hex(val))

	#
	def setCANReg(self):
		val = int(self.tfCAN_Register.get("1.0", tk.END))
		reg = MCP2515_regs[self.comboCAN_Register.get()]
		self.can.setReg(eg, val)

	#
	def txCANMsg(self):
		row = self.posTableTx.getSelRow()
		if(row > 0):
			txid = int(row[0], 0)
			dlc = int(row[1])
			b = []
			for i in range (0, dlc):
				b.append(int(row[i + 2], 0))
			self.can.addToTransmitQueue(txid, dlc, b)

	#
	def clearRXCAN(self):
		self.tfCANRX.delete("1.0", tk.END)

	#
	def canMsgReceived(self, rxdata):
		row = 0
		while row < 10:
			if (self.can_rx_ids[row] == -1) or (rxdata[0] == self.can_rx_ids[row]):
				self.can_rx_ids[row] = rxdata[0]
				row += 1
				self.posTableRx.setCellValue(row, 1, hex(rxdata[0]))
				self.posTableRx.setCellValue(row, 2, rxdata[1])
				for i in range (0, rxdata[1]):
					self.posTableRx.setCellValue(row, 3 + i, hex(rxdata[i + 2]))
				for i in range (rxdata[1], 8):
					self.posTableRx.setCellValue(row, 3 + i, '')
				break
			else:
				row = row + 1

	#
	def update(self):
		pass
