from Tkinter import *
import tkMessageBox
import Tkinter


class Application(object):
	"Graphical user interface for a DNA reader application"

	def __init__(self):
		# Set up plasmid reader
		self.currentDisplay = None

		# Create the overall frame
		self.frame = Tkinter.Frame()
		self.top = self.frame.winfo_toplevel()
		self.top.title("HES DNA reader")
		self.top.columnconfigure(0, weight=1)
		self.top.rowconfigure(0, weight=1)
		self.frame.columnconfigure(0, weight=1)
		self.frame.grid(row=0, column=0, sticky="news")
		self.frame.rowconfigure(1, weight=1)

		# Create frame containing data entry widgets
		f = Tkinter.Frame(master=self.frame)
		f.grid(row=0, column=0, sticky="ew")
		self._makeDataEntryWidgets(f) #populate this frame

		#make a label that gives some example of entries
		lab = Tkinter.Label(master = f, text="Enter values in one or more entry boxes. For primer entries: id should be a number (e.g. 140.0). For plasmid entries: id should be something like JSO123.")
		lab.grid(row=2, column=0, sticky="w")

		# Create text widget for displaying transactions
		import tkFont
		self.font = tkFont.Font(family="courier", size=12)
		self.boldFont = tkFont.Font(family="courier", size=12,
						weight="bold")
		self.text = Tkinter.Text(master=self.frame,
						width=100,
						wrap="char",
						font=self.font)
		self.text.grid(row=1, column=0, sticky="news")

	def _makeDataEntryWidgets(self, f):
		# Create list of buttons for initiating actions
		f.columnconfigure(0, weight=1)
		buttonFrame = Tkinter.Frame(master=f, pady=5)
		buttonFrame.grid(row=1, column=0, sticky="e")
		buttonUpdate = Tkinter.Button(master=buttonFrame, width=8,
						text="update!",
						command=self._update)
		buttonUpdate.grid(row=0, column=0, padx=5)
		buttonClear = Tkinter.Button(master=buttonFrame, width=8,
						text="clear!",
						command=self._clear)
		buttonClear.grid(row=0, column=1, padx=5)

		# Create data entry widgets
		global widgetFrame
		widgetFrame = Tkinter.Frame(master=f, pady=5, padx=5)
		widgetFrame.grid(row=0, column=0, sticky="ew")
		widgetFrame.columnconfigure(1, weight=1)

		l = Tkinter.Label(master=widgetFrame, text="DNA type:")
		l.grid(row=0, column=0, sticky="e")
		typeFrame = Tkinter.Frame(master=widgetFrame)
		typeFrame.grid(row=0, column=1, sticky="w")

		self.typeVar = Tkinter.StringVar(typeFrame)
		b = Tkinter.Radiobutton(master=typeFrame, text="Primer",
						value="primer",
						variable=self.typeVar, 
						command = self._primerside)				
		b.grid(row=0, column=0)
		b = Tkinter.Radiobutton(master=typeFrame, text="Plasmid",
						value="plasmid",
						variable=self.typeVar,
						command = self._plasmidside)
		b.grid(row=0, column=1)
		self.typeVar.set("plasmid") 

	def _primerside(self):
		[self.idlabel, self.id] = self._addEntry(widgetFrame, 1, "id")
		[self.desclabel, self.desc] = self._addEntry(widgetFrame, 2, "description")
		[self.substrlabel, self.substr] = self._addEntry(widgetFrame, 3, "sequence")

	def _plasmidside(self):
		self.desc.grid_remove()
		self.desclabel.grid_remove()
		self.substr.grid_remove()
		self.substrlabel.grid_remove()

	def _addEntry(self, f, row, label):
		l = Tkinter.Label(master=f, text=label + ":")
		l.grid(row=row, column=0, sticky="e")
		e = Tkinter.Entry(master=f)
		e.grid(row=row, column=1, sticky="ew")
		return [l, e]

	def _clear(self):
		self.text.delete("1.0", "end") #erase everything

	def _update(self):
		"Callback function when Update button is pressed"
		#gets all the information entered
		sid = self.id.get().strip()
		primer_desc = self.desc.get().strip()
		#print primer_desc
		#if not primer_desc:
		#	print type(primer_desc)
		primer_substr = self.substr.get().strip()

		#if nothing is entered
		if not sid and not primer_desc and not primer_substr:
			self.complain("Enter values in one or more of the boxes")
			return

		if self.typeVar.get() == "plasmid": #need to link up plasmid with plasmid radio button
			import plasmid_process
			[description, selection, sequence, promoter, gene, fluorophore]= plasmid_process.make_dictionaries()
			plasmid_info = plasmid_process.match_id(sid,description, selection, sequence, promoter, gene, fluorophore)
			if not plasmid_info:
				self.complain("'%s' does not match any sequence" % sid)
				return

			#display sequence in text field
			self.text.delete("1.0", "end") #erase everything
			self.text.insert(INSERT, "description:"+" "+plasmid_info[0]) #show description
			self.text.insert(INSERT, "\n")
			self.text.insert(INSERT, "selection:"+" "+plasmid_info[1])
			self.text.insert(INSERT, "\n")
			self.text.insert(INSERT, "sequence:"+" "+plasmid_info[2])
			self.text.insert(INSERT, "\n")
			self.text.insert(INSERT, "promoter:"+" "+plasmid_info[3])
			self.text.insert(INSERT, "\n")
			self.text.insert(INSERT, "gene:"+" "+plasmid_info[4])
			self.text.insert(INSERT, "\n")
			self.text.insert(INSERT, "fluorophore:"+" "+plasmid_info[5])

		if self.typeVar.get() == "primer":
			import primer_process
			[primer_description, primer_sequence] = primer_process.make_primer_dictionaries()

			#case1: only id is filled out 
			if not primer_desc and not primer_substr:
				primer_info = primer_process.id_search(sid, primer_description, primer_sequence)
				if primer_info == False:
					self.complain("'%s' does not match any sequence" %sid)
					return
				#display sequence
				self.text.delete("1.0", "end") #erase everything
				self.text.insert(INSERT, "description:"+" "+primer_info[0])
				self.text.insert(INSERT, "\n")
				self.text.insert(INSERT, "sequence:"+" "+primer_info[1])

			#case2: only description is filled out
			if not sid and not primer_substr:
				primer_info = primer_process.desc_search(primer_desc, primer_description, primer_sequence)

				if primer_info == False:
					self.complain("'%s' does not match any primer sequence description" %primer_desc)
					return

				#display sequence
				self.text.delete("1.0", "end") #erase everything
				for i in range(len(primer_info)): #loop through each primer info box thing
					primer_info1= primer_info[i]
					for j in range(len(primer_info1)): #loop through each id thing
						self.text.insert(INSERT, primer_info1[j])
						self.text.insert(INSERT, "\n")
					self.text.insert(INSERT, "\n")
					self.text.insert(INSERT, "\n")

			#case3: only sequence substring is filled out
			if not sid and not primer_desc:
				primer_info = primer_process.substr_search(primer_substr, primer_description, primer_sequence)
				if primer_info == False:
					self.complain("'%s' does not match any primer sequence" %primer_substr)
					return

				#display sequence
				self.text.delete("1.0", "end") #erase everything
				for i in range(len(primer_info)): #loop through each primer info box thing
					primer_info1= primer_info[i]
					for j in range(len(primer_info1)): #loop through each id thing
						self.text.insert(INSERT, primer_info1[j])
						self.text.insert(INSERT, "\n")
					self.text.insert(INSERT, "\n")
					self.text.insert(INSERT, "\n")

			#case4: only primer description and sequence are filled out 
			if not sid:
				primer_info = primer_process.combo(primer_desc, primer_substr, primer_description, primer_sequence)
				if primer_info == False: #case where there is no intersection between the primer desc and sequence enter
					printout = str(primer_desc)+" "+"and"+" "+str(primer_substr)
					self.complain("There is no primer that contrain both '%s' substrings in their description or sequence" %printout)

				#display sequence
				self.text.delete("1.0", "end") #erase everything
				for i in range(len(primer_info)): #loop through each primer info box thing
					primer_info1= primer_info[i]
					for j in range(len(primer_info1)): #loop through each id thing
						self.text.insert(INSERT, primer_info1[j])
						self.text.insert(INSERT, "\n")
					self.text.insert(INSERT, "\n")
					self.text.insert(INSERT, "\n")

	def complain(self, msg):
		"Display an error message and wait for user to hit Okay"
		from tkMessageBox import showerror
		showerror(title="Error", message=msg)

	def run(self):
		"Run the Tk event loop for the graphical user interface"
		self.top.mainloop()

if __name__ == "__main__":
	app = Application()
	app.run()