# -*- coding: utf-8 -*-®
'''
GUI written in QT5 to setup preferences
'''
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QComboBox, QLabel, QLineEdit, QMessageBox, QMainWindow,QSizePolicy, QFileDialog, QDialog
from PyQt5.QtGui import QStandardItemModel, QStandardItem, QDoubleValidator
from PyQt5.QtCore import Qt, QTimer

import numpy as np

import sys
#biasd_path = '/Users/colin/Desktop/20161220 biasd_release/biasd'

import biasd as b

from smd_loader import smd_load
from plotter import trace_plotter

class ui_set_tau(QMainWindow):
	def __init__(self,parent=None):
		super(QMainWindow,self).__init__(parent=parent)
		self.initialize()

	def initialize(self):
		p = self.parent().parent().parent().prefs
		tau = p.tau
		
		self.statusBar()
		
		qw = QWidget()
		hbox = QHBoxLayout()
		
		ltau = QLabel(u"τ (s):")
		
		self.le_tau = QLineEdit()
		self.le_tau.setValidator(QDoubleValidator(1e-300,1e300,100))
		self.le_tau.editingFinished.connect(self.update_tau)
		self.le_tau.setText(str(tau))

		bset = QPushButton('Set')
		bset.clicked.connect(self.update_tau)
		
		[hbox.addWidget(bb) for bb in [ltau,self.le_tau,bset]]
		qw.setLayout(hbox)
		self.setCentralWidget(qw)
		self.setWindowTitle('Set tau')
		self.show()
		
		self.le_tau.selectAll()
	
	def keyPressEvent(self,event):
		if event.key() == Qt.Key_Escape:
			self.close()
	
	def closeEvent(self,event):
		# self.ui.close()
		self.parent().setFocus()
		self.parent().raise_()
		self.parent().activateWindow()
		self.close()
	
	def update_tau(self):
		try:
			p = self.parent().parent().parent().prefs
			new_tau = float(self.le_tau.text())
			if p.tau != new_tau:
				p.tau = new_tau
				self.parent().parent().parent().log.new('Updated tau = '+str(p.tau))
				self.close()
			else:
				self.statusBar().showMessage("There's no change...")
			self.parent().update()
		except:
			pass
		self.setFocus()

	
class traces(QWidget):
	def __init__(self,parent):
		super(QWidget,self).__init__(parent=parent)
		self.initialize()

	def initialize(self):
		
		# Buttons | Plot
		hbox = QHBoxLayout()
		# Buttons
		qwbuttons = QWidget()
		vbox = QVBoxLayout()
		
		badd = QPushButton('Import')
		btranspose = QPushButton('Transpose')
		bprev = QPushButton('<<')
		bnext = QPushButton('>>')
		bappend = QPushButton('Commit')
		
		bprev.clicked.connect(self.prev_trace)
		bnext.clicked.connect(self.next_trace)
		btranspose.clicked.connect(self.transpose_traces)
		bappend.clicked.connect(self.append_to_smd)
		badd.clicked.connect(self.add_traces)

		qwtemp = QWidget()
		hbox3 = QHBoxLayout()
		[hbox3.addWidget(bb) for bb in [badd,btranspose]]
		hbox3.addStretch(1)
		qwtemp.setLayout(hbox3)
		vbox.addWidget(qwtemp)

		qwtemp = QWidget()
		hbox2 = QHBoxLayout()
		hbox2.addStretch(1)
		[hbox2.addWidget(bb) for bb in [bprev,bnext]]
		hbox2.addStretch(1)
		qwtemp.setLayout(hbox2)
		vbox.addWidget(qwtemp)
		
		bset_tau = QPushButton(u'&Set τ')
		bset_tau.clicked.connect(self.launch_set_tau)
		vbox.addWidget(bset_tau)
		
		vbox.addStretch(1)
		
		vbox.addWidget(bappend)
		
		qwbuttons.setLayout(vbox)
		hbox.addWidget(qwbuttons)
		
		# Plot
		self.fig = trace_plotter(self)
		hbox.addWidget(self.fig)
		self.stretcher = hbox.addStretch(1)
		
		self.buttons = [badd,btranspose,bprev,bnext,bappend,bset_tau]
		
		self.setLayout(hbox)
		self.setWindowTitle('Import Traces')
		self.setFocus()
		self.show()
	
	def launch_set_tau(self):
		try:
			self.ui_tau.close()
		except:
			pass
		self.ui_tau = ui_set_tau(self)
	
	def transpose_traces(self):
		try:
			d1,d2 = self.imported_data.shape
			if d1 > 1 and d2 > 1:
				self.imported_data = self.imported_data.T
				self.trace_index = 0
				self.update_figure()
		except:
			pass
	
	def jump_trace(self,i):
		try:
			ni = int(i + self.trace_index)
			if ni < 0:
				ni = 0
			elif ni >= self.imported_data.shape[0]:
				ni = self.imported_data.shape[0] -1
			self.trace_index = ni
			self.update_figure()
		except:
			pass
	
	def next_trace(self):
		self.jump_trace(1)
		
	def prev_trace(self):
		self.jump_trace(-1)
		
	def update_figure(self):
		tau = self.get_safe_tau()
		d = self.imported_data[self.trace_index]
		title = str(self.trace_index) + "/"+str(self.imported_data.shape[0]-1)
		self.fig.plot_trace(np.arange(d.size)*tau,d,title=title)
		self.setFocus()
	
	def update(self):
		self.update_figure()
	
	def get_safe_tau(self):
		try:
			p = self.parent().parent().prefs
			tau = p.tau
		except:
			tau = 1.
		return tau
	
	def add_traces(self):
		fname = str(QFileDialog.getOpenFileName(self,
			"Choose data file to load trajectories from","./")[0])
		data = False
		if fname:
			try:
				self.imported_data = b.smd.loadtxt(fname)
				if self.imported_data.ndim == 1:
					self.imported_data = self.imported_data[np.newaxis,:]
				data = True
			except:
				QMessageBox.critical(self,'Could not Load',
					'Could not load file: %s. It should be either an (N,T) or (T,N) array with tab, space, or comma delimiters. It can also be a binary numpy ndarray.'%(fname))
		if data:
			self.trace_index = 0
			self.update_figure()
			
	def append_to_smd(self):
		doit = False
		d = self.imported_data
		fname = self.parent().parent().filename
		try:
			f = b.smd.load(fname)
			# check if this is maybe the same
			doit = True
			if f.attrs.keys().count('number of trajectories'):
				nn = f.attrs['number of trajectories']
				if nn == d.shape[0]:
					really = QMessageBox.question(self,'Are you sure?', 'It looks like %s already contains %d trajectories. Are you sure you want to *APPEND* these new trajectories? You will have %d trajectories then.'%(fname, nn, 2*nn))
					if really != QMessageBox.Yes:
						doit = False
		except:
			try:
				f.close()
			except:
				pass
			
		if doit:
			tau = self.parent().parent().prefs.tau
			t = np.arange(d.shape[1])*tau
			b.smd.add.trajectories(f,t,d)
			for i in range(d.shape[0]):
				group = f['trajectory %d'%(i)]
				group.attrs['tau'] = tau
				group.attrs['added by'] = 'BIASD GUI v.'+self.parent().parent().__version__
			
			#Be REAL safe
			try:
				b.smd.save(f)
				self.parent().parent().log.new('Appended %d Trajectories onto: \n    %s '%(d.shape[0],fname))
				self.parent().parent().parent().statusBar().showMessage("%d New Trajectories Added..."%(d.shape[0]))
			except:
				pass
		
	
	def closeEvent(self,event):
		self.close()
		self.parent().close()
	
	def keyPressEvent(self,event):
		if event.key() == Qt.Key_Escape:
			for b in self.buttons:
				if b.hasFocus():
					self.setFocus()
					return
			self.close()
			self.parent().close()
		elif event.key() == Qt.Key_Right:
			self.next_trace()
		elif event.key() == Qt.Key_Left:
			self.prev_trace()
		elif event.key() == Qt.Key_Up:
			try:
				d = self.imported_data.shape[0]
				self.jump_trace(-d)
			except:
				pass
		elif event.key() == Qt.Key_Down:
			try:
				d = self.imported_data.shape[0]
				self.jump_trace(d)
			except:
				pass
		
		elif event.key() == Qt.Key_I:
			self.add_traces()
		elif event.key() == Qt.Key_C:
			self.append_to_smd()
		elif event.key() == Qt.Key_S:
			self.launch_set_tau()
		elif event.key() == Qt.Key_T:
			self.transpose_traces()

class ui_traces(QMainWindow):
	def __init__(self,parent=None):
		super(QMainWindow,self).__init__(parent)
		self.ui = traces(self)
		# self.setGeometry(100,100,600,400)
		self.setCentralWidget(self.ui)
		self.setFocus()
		
		self.show()
	
	def keyPressEvent(self,event):
		self.ui.keyPressEvent(event)
	
	def closeEvent(self,event):
		self.ui.close()
		self.parent().activateWindow()
		self.parent().raise_()
		self.parent().setFocus()
		self.close()
		
if __name__ == '__main__':
	import sys
	app = QApplication(sys.argv)
	w = ui_traces()
	sys.exit(app.exec_())
