#  Copyright 2017 Carlos Pascual-Izarra <cpascual@users.sourceforge.net>
#
#  This file is part of PeakEvo.
#
#  PeakEvo 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 3 of the License, or
#  (at your option) any later version.
#
#  PeakEvo 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.
#
# You should have received a copy of the GNU General Public License
# along with Foobar.  If not, see <http://www.gnu.org/licenses/>.

from __future__ import absolute_import

import os
import sys

import numpy
from qtpy import QtCore, QtWidgets, uic


class PressureCalib(QtWidgets.QDialog):
    """A widget to calibrate the pressure reading.
    It correlates raw serial voltage reads with user-provided pressures
    """

    apply = QtCore.Signal(object)

    def __init__(self, pressureReader, parent=None):
        QtWidgets.QDialog.__init__(self, parent=parent)

        # load ui
        uipath = os.path.join(os.path.dirname(__file__), "pcalib.ui")
        uic.loadUi(uipath, self)

        self._pressureReader = pressureReader
        self.calib = numpy.array([1, 0], dtype="float64")

        self._timer = QtCore.QTimer()
        self._timer.timeout.connect(self._updateRaw)
        self._timer.start(100)

        self.valuesTE.textChanged.connect(self._updateCalib)
        self.addPointBT.clicked.connect(self._onAdd)

    def _onAdd(self):
        raw = self._pressureReader.raw()
        p, ok = QtWidgets.QInputDialog.getDouble(
            self,
            "Add calibration point",
            "Pressure? (raw={:.0f})".format(raw),
            decimals=2,
        )
        if ok:
            text = self.valuesTE.toPlainText().strip()
            self.valuesTE.setPlainText(text + "\n{:04.0f}\t{:.1f}".format(raw, p))

    def _updateRaw(self):
        raw = self._pressureReader.raw()
        self.rawSB.setValue(round(raw))
        self._updatePressure(raw)

    def _updateCalib(self):
        try:
            values = numpy.fromstring(self.valuesTE.toPlainText(), sep=" ")
            x, y = (values.reshape((values.size / 2, 2))).T
            if len(y) < 2:
                return
            g, o = self.calib = numpy.polyfit(x, y, 1)
            self.gainSB.setValue(g)
            self.offsetSB.setValue(o)
        except Exception:
            pass

    def _updatePressure(self, raw):
        self.pressure.display("{:05.1f}".format(numpy.polyval(self.calib, raw)))

    def _onApply(self):
        self.apply.emit(self.calib)


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)

    from .pressure import DummyPressureSensor as PressureSensor

    sensor = PressureSensor()

    w = PressureCalib(sensor)
    w.show()

    sys.exit(app.exec_())
