import sys
import os, time
from PyQt5 import QtWidgets, QtCore
from PyQt5.QtGui import QPixmap, QIcon,QFont
from PyQt5.QtWidgets import QGraphicsScene,QGraphicsPixmapItem
from PyQt5.QtCore import Qt  # Import Qt for alignment
from .layouts.gauge import Gauge
from .interactive.myUtils import CustomGraphicsView
from .layouts import ui_Counter
from .utilities.devThread import Command
import numpy as np
class Expt(QtWidgets.QWidget, ui_Counter.Ui_Form):
    def __init__(self, device, **kwargs):
        super().__init__()
        self.setupUi(self)
        time.sleep(0.2)
        self.last_counts = 0
        self.input = 'SEN'
        self.startCounts = 0
        self.start_time = time.time()

        self.scope_thread = None
        self.running = False
        if 'scope_thread' in kwargs:
            self.scope_thread = kwargs['scope_thread']
            self.scope_thread.add_command(Command('set_sqr1',{'frequency':0,'duty_cycle':0.5}))
            self.scope_thread.add_command(Command('start_counter',{'channel':'SEN'}))
            self.scope_thread.add_command(Command('pause_counter',{'channel':'SEN'}))

            self.scope_thread.counts_ready.connect(self.setCounts)

        self.showMessage = print

        if 'set_status_function' in kwargs:
            self.set_status_function(kwargs['set_status_function'])

        
        self.gauge_widget = Gauge(self, 'COUNTS')
        self.gauge_widget.setObjectName('COUNTS')
        self.gauge_widget.set_MinValue(0)
        self.max_value = 100
        self.gauge_widget.set_MaxValue(self.max_value)
        self.gauge_widget.setMinimumWidth(300)
        self.gaugeLayout.addWidget(self.gauge_widget)


        # Create a layout for the right side (image)
        image_widget = QtWidgets.QWidget()  # Placeholder for the image
        

        self.scene = QGraphicsScene(self)
        self.view = CustomGraphicsView(self.scene)
        self.view.setFrameShape(QtWidgets.QFrame.NoFrame)  # Remove the frame border

        imagepath = os.path.join(os.path.dirname(__file__),'interactive/flywheel.jpg')
        mypxmp = QPixmap(imagepath)
        myimg = QGraphicsPixmapItem(mypxmp)
        myimg.setTransformationMode(Qt.SmoothTransformation)
        self.scene.addItem(myimg)

        self.gaugeLayout.addWidget(self.view)

        # Create a horizontal frame for radio buttons and warning label
        self.startButton.setIcon(QIcon(os.path.join("layouts","play.svg")))
        self.startButton.setIconSize(QtCore.QSize(40, 40))

        self.stopButton.setIcon(QIcon(os.path.join("layouts","pause.svg")))
        self.stopButton.setIconSize(QtCore.QSize(40, 40))
        self.splitter.setSizes([100, 100])

        # Create plots
        self.MAXPOINTS = 10000
        self.datapoints = 0
        self.distance_plot = self.plotLayout.addPlot()

        self.time_data = np.empty(300)
        self.distance_data = np.empty(300)
        self.velocity_data = np.empty(300)
        self.datapoints=0

        self.distance_curve = self.distance_plot.plot(self.distance_data[0:self.datapoints])
        self.plotLayout.nextRow()
        self.velocity_plot = self.plotLayout.addPlot()
        self.velocity_plot.setLimits(yMin=0)
        self.velocity_data = np.zeros(self.MAXPOINTS)
        self.velocity_curve = self.velocity_plot.plot(self.velocity_data[0:self.datapoints])   

        self.distance_plot.setLabel('left', 'Distance')
        self.distance_plot.setLabel('bottom', 'Time')
        self.velocity_plot.setLabel('left', 'Velocity')
        self.velocity_plot.setLabel('bottom', 'Time')


        # Create a QTimer for periodic voltage measurement
        self.timer = QtCore.QTimer(self)
        self.timer.timeout.connect(self.fetch_counts)  # Connect the timeout signal to the update method
        self.timer.start(200)  # Start the timer with a 200ms interval


    def set_status_function(self,func):
        self.showMessage = func

    def fetch_counts(self):
        if not self.running: return
        self.scope_thread.add_command(Command('get_counts',{}))

    def setCounts(self,counts):
        self.last_counts = counts
        if counts > self.max_value and self.max_value<2e32:
            self.max_value = self.max_value*2
            self.gauge_widget.set_MaxValue(self.max_value)
            self.showMessage(f'Range increased to {self.max_value}', 2000)

        self.gauge_widget.update_value(counts)  # Update the gauge with the new voltage value

        if not self.running: return
        if self.datapoints >= self.time_data.shape[0]-1:
            tmp = self.time_data    
            self.time_data = np.empty(self.time_data.shape[0] * 2) #double the size
            self.time_data[:tmp.shape[0]] = tmp
            tmp = self.distance_data
            self.distance_data  = np.empty(self.distance_data.shape[0] * 2) #double the size
            self.distance_data[:tmp.shape[0]] = tmp
            tmp = self.velocity_data
            self.velocity_data = np.empty(self.velocity_data.shape[0] * 2) #double the size
            self.velocity_data[:tmp.shape[0]] = tmp

        self.time_data[self.datapoints] = time.time()-self.start_time
        self.distance_data[self.datapoints] = counts

        
        vel_points=10
        if self.datapoints > vel_points:
            self.velocity_data[self.datapoints-vel_points-1] = (self.distance_data[self.datapoints]-self.distance_data[self.datapoints-vel_points-1])/(self.time_data[self.datapoints]-self.time_data[self.datapoints-vel_points-1])
            self.velocity_curve.setData(self.time_data[0:self.datapoints-vel_points],self.velocity_data[0:self.datapoints-vel_points])
            self.velocity_curve.setPos(-self.time_data[self.datapoints], 0)

        self.distance_curve.setData(self.time_data[0:self.datapoints],self.distance_data[0:self.datapoints])
        self.distance_curve.setPos(-self.time_data[self.datapoints], 0)

        self.datapoints += 1



    def startCounter(self):
        self.last_counts = 0
        self.scope_thread.add_command(Command('start_counter',{'channel':self.input}))
        self.start_time = time.time()

        self.time_data = np.empty(300)
        self.distance_data = np.empty(300)
        self.velocity_data = np.empty(300)
        self.datapoints=0
        print("Starting counter")
        self.running = True


    def pauseCounter(self):
        self.running = not self.running
        if not self.running:    
            self.stopButton.setIcon(QIcon(os.path.join("layouts","play.svg")))
            self.stopButton.setText('Resume')
            self.scope_thread.add_command(Command('pause_counter',{}))
        else:
            self.stopButton.setIcon(QIcon(os.path.join("layouts","pause.svg")))
            self.stopButton.setText('Pause')
            self.scope_thread.add_command(Command('resume_counter',{}))

    def setInput(self,input):
        if input == 0:
            self.input = 'SEN'
        else:
            self.input = 'IN2'
        if self.running:
            self.startCounter()

    def set_sqr1(self):
        f = self.sqr1_freq.value()
        self.scope_thread.add_command(Command('set_sqr1',{'frequency':f,'duty_cycle':0.5}))
        if f == 0:
            self.sqr1_label.setText('SQR1 Frequency : ALWAYS ON')
        else:
            self.sqr1_label.setText(f'SQR1 Frequency ( 0 = ALWAYS ON) : {f} Hz')
# This section is necessary for running new.py as a standalone program

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    window = Expt(None)  # Pass None for the device in standalone mode
    window.show()
    sys.exit(app.exec_()) 