# Includes
# --------------------------------------------------------------------------- #
import numpy as np
#from Main.firmware.Package.ADS1x15 import ADS1x15
import adafruit_ads1x15.ads1115 as ADS_Nuevo
from adafruit_ads1x15.analog_in import AnalogIn
import board
import busio
import time
from scipy.signal import savgol_filter

class Ads():
    def __init__(self, address = "0x48", adc_gain=1):  # adc_gain=2/3
        # Ganancias:
        # 2/3	±6.144V
        # 1	    ±4.096V
        # 2	    ±2.048V
        # 4	    ±1.024V
        # 8	    ±0.512V
        # 16	±0.256V
        self.gain = 1
        self.address = address
        self.samples = [0, 0, 0]
        self.nsamples = 50
        self.data_rate = 860 # muestras en 1 segundo
        # Create the I2C bus
        i2c = busio.I2C(board.SCL, board.SDA)
        # Create the ADC object using the I2C bus
        self.adc = ADS_Nuevo.ADS1115(i2c=i2c, gain=self.gain, data_rate=self.data_rate)
        self.canales = {
            0: AnalogIn(self.adc, ADS_Nuevo.P0),
            1: AnalogIn(self.adc, ADS_Nuevo.P1),
            2: AnalogIn(self.adc, ADS_Nuevo.P2),
        }
        self.last = [0,0,0]

    def sense_cb(self, nsamples, lsr):
        M = np.asarray([self.canales[lsr].value for _ in np.arange(nsamples)])
        M = np.sort(M)
        #print(M)
        return np.average(M[:-5])

    def sense(self, corr_fact=[1, 1, 1]):
        a = [self.canales[0].value for _ in np.arange(self.nsamples)]
        b = [self.canales[1].value for _ in np.arange(self.nsamples)]
        c = [self.canales[2].value for _ in np.arange(self.nsamples)]
        return [int(np.max(np.asarray(a))),
                int(np.max(np.asarray(b))),
                int(np.max(np.asarray(c)))]
    
    def sense_bulk(self):
        t_in = time.perf_counter()
        M = np.asarray([
            # Data rate must be one of: 8, 16, 32, 64, 128, 250, 475, 860
            (   self.adc.read(0, self.gain, 475),
                self.adc.read(1, self.gain, 475),
                self.adc.read(2, self.gain, 475))
                for _ in np.arange(self.nsamples)]).astype(int).transpose()
        
        laser1 = M[0,:]
        laser2 = M[1,:]
        laser3 = M[2,:]
        t_meas = time.perf_counter() - t_in
        t_in = time.perf_counter()
        laser1_filt = savgol_filter(laser1, 2, 0).astype(int).tolist()
        laser2_filt = savgol_filter(laser2, 2, 0).astype(int).tolist()
        laser3_filt = savgol_filter(laser3, 2, 0).astype(int).tolist()
        t_filt = time.perf_counter() - t_in

        return  [laser1.tolist(), laser2.tolist(), laser3.tolist()], [laser1_filt, laser2_filt, laser3_filt], t_meas, t_filt

    def sense_bulk_single(self):
        return [self.adc.read(0) for _ in np.arange(self.nsamples)]

    def sense_single(self):
        M = []
        T = []
        for _ in range(self.nsamples):
            t_in = time.perf_counter()
            m = self.adc.read(0)
            t_f = time.perf_counter() - t_in
            M.append(m)
            T.append(t_f)
        return M, T
    
    def Estado(self):
        if all(x>1 for x in self.sense()):
            return 0
        if any(x>1 for x in self.sense()):
            return 1
        return 2