
import os
from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtGui import QIcon, QPalette, QPixmap
from PyQt5.QtWidgets import qApp, QAction, QFileDialog, QLabel, QMainWindow, QWidget
from fexqt.spectrogram import Spectrogram
from fexqt.config import configure


class MainWin(QMainWindow):
	def __init__(self, files):
		super().__init__()
		self.files = files
		self.config = configure()
		self.setGeometry(0, 0, 800, 600)
		self.setWindowTitle("Fex: Frequency Excursion Calculator")
		self.setWindowIcon(QIcon('web.png'))	# FIXME
		if self.config['main-window']['maximized']:
			self.setWindowState(Qt.WindowMaximized)
		self.init_calls()
		self.init_actions()
		self.init_menubar()
		self.init_toolbar()
		self.init_statusbar()
		self.init_body()
		self.show()
		self.spect = None
		# Spectrograms are sized relative to parent window.  The timer allows
		# the window manager to adjust the parent window prior to this sizing.
		if self.files:
			QTimer.singleShot(20,self.next_spectrogram)

	# TODO handle drag & drop of sound files to add to queue
	# and update window title

	def action_unknown(self):
		print(' WARN: unknown action binding')

	def action_add_songs(self):
		fnames, kind = QFileDialog.getOpenFileNames(self, 'Select Audio Files', os.getcwd(), "Audio (*.wav)")
		if not fnames:
			return
		self.files += fnames
		if self.spect:
			self.setWindowTitle(self.basename + ' [+%d more]' % len(self.files))
		else:
			self.next_spectrogram()

	def init_calls(self):
		self.calls = {
			'add_songs': self.action_add_songs,
			'fit': lambda: self.spect.fit() if self.spect else None,
			'mode_normal': lambda: self.spect.mode_normal() if self.spect else None,
			'mode_cursor': lambda: self.spect.mode_cursor() if self.spect else None,
			'mode_eraser': lambda: self.spect.mode_eraser() if self.spect else None,
			'quit': qApp.quit,
			'unknown': self.action_unknown,
		}

	def init_body(self):
		self.body = QWidget()
		self.body.setBackgroundRole(QPalette.AlternateBase)
		self.body.setAutoFillBackground(True)
		self.body.setContentsMargins(10,10,10,10)
		self.setCentralWidget(self.body)

	def init_actions(self):
		self.actions = dict()
		for act in self.config['actions']:
			pix = QPixmap()
			pix.loadFromData(act['icon'])
			a = QAction(QIcon(pix), act['menu'], self)
			a.setShortcut(act['shortcut'])
			a.setStatusTip(act['statustip'])
			if act['name'] in self.calls:
				a.triggered.connect(self.calls[act['name']])
			else:
				a.triggered.connect(self.calls['unknown'])
			self.actions[act['name']] = a

	def init_menubar(self):
		self.menubar = self.menuBar()
		fileMenu = self.menubar.addMenu('&File')
		fileMenu.addAction(self.actions['quit'])
		fileTools = self.menubar.addMenu('&Tools')
		fileTools.addAction(self.actions['mode_normal'])
		fileTools.addAction(self.actions['mode_cursor'])
		fileTools.addAction(self.actions['mode_eraser'])

	def init_statusbar(self):
		self.statusbar = self.statusBar()
		self.status_text = QLabel()
		self.statusBar().addPermanentWidget(self.status_text)

	def init_toolbar(self):
		for bar in self.config['main-window']['toolbars']:
			toolbar = self.addToolBar(bar['name'])
			toolbar.setVisible(bar['visible'])
			toolbar.setToolButtonStyle(bar['style'])
			for item in bar['items']:
				if item == 'bar':
					toolbar.addSeparator()
				else:  # if act[''] exists
					toolbar.addAction(self.actions[item])

	def next_spectrogram(self):
		if self.spect:
			pass # TODO save data and print(' DATA: ...')
		if self.files:
			fname = self.files.pop(0)
			self.basename = os.path.basename(fname)
			title = self.basename
			if self.files:
				title += ' [+%d more]' % len(self.files)
			self.setWindowTitle(title)
			self.spect = Spectrogram(fname, self.body, self.config['spectrogram'])
			self.spect.fexChanged.connect(self.update_status_fex)
			self.spect.mouseOver.connect(self.update_status_text)
		else:
			self.fname = None
			self.spect = None

	def update_status_fex(self, pex, tex):
		self.pex = pex
		self.tex = tex
		try:
			self.fex = pex / tex
		except ZeroDivisionError:
			self.fex = 0.0

	def update_status_text(self, x, y):
		self.status_text.setText("FEX: %.3f   %0.3fs %0.1fKHz" %(self.fex,x,y))

