# -*- coding: utf-8 -*-
"""

@author: 3CO

Version de V25 adaptada para la bd del AS400 XSORTER para la version de grabacion y muestra de video

Visual Check con grabacion de video, sin grabacion de fotos.
"""

# FICHERO DE CONFIGURACION, DEBE ESTAR EN LA MISMA CARPETA QUE EL EXE


import cv2
import time
import sqlite3
import numpy as np
from win32api import GetSystemMetrics
import threading
from datetime import datetime, timedelta
import os
import sys
import subprocess
import glob
from copy import deepcopy
import json
import traceback
import psutil
import socket
import psycopg2
import psycopg2.extras
import aux_function as aux
import requests


class VideoGet:
    def __init__(self, src=0,idcamara=0):
        self.src = src
        self.stopped = False
        self.Q = []
        self.scale_percent = 50
        self.grabbed = False
        self.frame = None
        self.idcamara = idcamara
    def start(self):
        threading.Thread(target=self.get, args=()).start()
        return self

    def get(self):
        while True:
            preFrame = []
            self.stream = cv2.VideoCapture(self.src)
            (self.grabbed, preFrame) = self.stream.read()
            self.ceros = np.sum(preFrame)
            if (self.ceros is None):
                self.ceros = 0
            if self.ceros >= 1000000 and self.ceros is not None:
                print('Iniciando camara. Valor Inicial: ' + str(self.ceros))
                while True:
                    try:
                        (self.grabbed, preFrame) = self.stream.read()
                        self.width = int(preFrame.shape[1] * self.scale_percent / 100)
                        self.height = int(preFrame.shape[0] * self.scale_percent / 100)
                        dim = (self.width, self.height)
                        self.frame = cv2.resize(preFrame, dim, interpolation=cv2.INTER_AREA)
                        if len(self.Q) >= cfg['PARAMETROS']['tiempoPre']:
                            self.Q.pop(0)
                            self.Q.append(self.frame)
                        else:
                            self.Q.append(self.frame)
                    except Exception as e:
                        self.stream.release()
                        break

    def stop(self):
        self.stopped = True


class VideoShow:
    def __init__(self, camara, nombre):
        self.camara = camara
        self.stopped = False
        self.marcado = False
        self.frame = ''
        self.idcamara = 1
        self.nombre = nombre

    def start(self):
        threading.Thread(target=self.show, args=()).start()
        return self

    def show(self):
        while True:
            self.frame = self.camara.frame
            try:
                cv2.imshow(self.nombre, cv2.resize(self.frame, None, fx=0.4, fy=0.4, interpolation=cv2.INTER_CUBIC))
                if cv2.waitKey(1) == ord("q"):
                    self.stopped = True
            except:
                time.sleep(1)

    def stop(self):
        self.stopped = True
        self.cerrarVentana()

    def setMarcado(self, valor):
        self.marcado = valor

    def cerrarVentana(self):
        cv2.destroyAllWindows()


# Genera fotos cuando hay peticiones
def Peticiones(conn, camaras,rampa):


    while True:
        cursor = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
        # Se detecta peticion
        sql = f"SELECT A.RAS,PIC,ZONA,COALESCE(REFERENCIA,'') AS REFERENCIA,COALESCE(DES_REFERENCIA,'') AS DES_REFERENCIA,C.IDCAMARA,COALESCE(A.TIENDA,'') AS TIENDA FROM PETICIONES A LEFT JOIN PARAMETRIZACION B ON A.RAS = B.RAMPA LEFT JOIN CAMARAS C ON B.IDCAMARA = C.IDCAMARA WHERE ERRORES IS NULL AND A.RAS = '{rampa}' ORDER BY MOMENTO_INICIO"
        cursor.execute(sql)
        datosPeticion = {}
        for rowPeticiones in cursor.fetchall():
            rampa = rowPeticiones['ras']
            datosPeticion['VS2RAS'] = rowPeticiones['ras']
            datosPeticion['VS2REF'] = rowPeticiones['referencia']
            datosPeticion['VS2DES'] = rowPeticiones['des_referencia']
            datosPeticion['VS2PEN'] = rowPeticiones['tienda']
            datosPeticion['VS2PIC'] = rowPeticiones['pic']
            datosPeticion['VS2POS'] = rowPeticiones['zona']
            datosPeticion['IDCAMARA'] = rowPeticiones['idcamara']
            datosPeticion['strtiempo'] = time.strftime("%y/%m/%d %H:%M:%S")
            datosParametrizacion = {}
            sql = f"SELECT * FROM PARAMETRIZACION WHERE RAMPA='{datosPeticion['VS2RAS']}'"
            cursor.execute(sql)
            datosParametrizacion = cursor.fetchone()
            if datosParametrizacion is not None:
                print("Inicio del proceso para posicion:", datosPeticion['VS2POS'])
                total_fotos = 0
                datosZona = {}
                existe_pos = False
                sql = f"select * from zonas where zona='{datosPeticion['VS2POS']}' and ras='{datosPeticion['VS2RAS']}'"
                cursor.execute(sql)
                resultados = cursor.fetchall()
                for rowZonas in resultados:
                    existe_pos = True
                    datosZona['maximo_intentos'] = rowZonas['mili_seg_togo']
                    datosZona['umbralPropio'] = rowZonas['senszona']
                    if(cfg['LED']['hayLED'] == 1):
                        apagar_posiciones_anteriores(cursor,datosPeticion['VS2RAS'])
                        resultado, colorLED = encender_display(cursor,rowZonas['display_ptl'],datosPeticion['VS2RAS'])
                        datosZona['display'] = rowZonas['display_ptl']
                    else:
                        colorLED = 'AZUL'
                    if (datosZona['umbralPropio'] == ''):
                        datosZona['umbralPropio'] = datosParametrizacion[rampa]['umbral']
                    if rowZonas['cajas_act'] < rowZonas['cajas_ext']:
                        datosZona[rowZonas['zona'] + 'bxy'] = rowZonas['x_roi'], rowZonas['y_roi'], rowZonas['w_roi'], rowZonas['h_roi']
                        datosZona[rowZonas['zona'] + 'bxychg'] = 0
                        datosZona[rowZonas['zona'] + 'cxy'] = rowZonas['x_roi2'], rowZonas['y_roi2'], rowZonas['w_roi2'], rowZonas['h_roi2']
                        datosZona[rowZonas['zona'] + 'cxychg'] = 0
                        datosZona[rowZonas['zona'] + 'dxy'] = rowZonas['x_roi3'], rowZonas['y_roi3'], rowZonas['w_roi3'], rowZonas['h_roi3']
                        datosZona[rowZonas['zona'] + 'dxychg'] = 0
                        datosZona[rowZonas['zona'] + 'exy'] = rowZonas['x_roi4'], rowZonas['y_roi4'], rowZonas['w_roi4'], rowZonas['h_roi4']
                        datosZona[rowZonas['zona'] + 'exychg'] = 0
                    else:
                        datosZona[rowZonas['zona'] + 'bxy'] = rowZonas['x_roi_ext'], rowZonas['y_roi_ext'], rowZonas['w_roi_ext'], rowZonas[
                            'h_roi_ext']
                        datosZona[rowZonas['zona'] + 'bxychg'] = 0
                        datosZona[rowZonas['zona'] + 'cxy'] = rowZonas['x_roi2_ext'], rowZonas['y_roi2_ext'], rowZonas['w_roi2_ext'], rowZonas[
                            'h_roi2_ext']
                        datosZona[rowZonas['zona'] + 'cxychg'] = 0
                        datosZona[rowZonas['zona'] + 'dxy'] = rowZonas['x_roi3_ext'], rowZonas['y_roi3_ext'], rowZonas['w_roi3_ext'], rowZonas[
                            'h_roi3_ext']
                        datosZona[rowZonas['zona'] + 'dxychg'] = 0
                        datosZona[rowZonas['zona'] + 'exy'] = rowZonas['x_roi4_ext'], rowZonas['y_roi4_ext'], rowZonas['w_roi4_ext'], rowZonas[
                            'h_roi4_ext']
                        datosZona[rowZonas['zona'] + 'exychg'] = 0

                if existe_pos:
                    # Crea foto patron y en general todas las acciones de inicio del proceso
                    # Busca la camara a utilizar
                    for cam in camaras:
                        if cam.idcamara == datosPeticion['IDCAMARA']:
                            cam1 = cam
                    try:
                        foto1, ret = Hacer_foto(cam1, datosPeticion, 0)
                        foto1 = Balizar_foto(foto1, datosPeticion, 0, 'SI', cam1.scale_percent, datosParametrizacion)
                        analizar_actividad(cam1, datosPeticion, datosZona, foto1, datosParametrizacion,colorLED)
                    except Exception as e:
                        traceback.print_exc()
                        graba_log('peticiones', 'Excepcion al iniciar la comprobacion\n' + str(e))
                        

                else:
                    devolver_resultado(datosPeticion, 'NO_POSICION', 0)
                    print("No existe posición ", datosPeticion['VS2POS'])
                    graba_log('peticiones', 'No existe la posicion ' + datosPeticion['VS2POS'])

        time.sleep(1)



# Analizar la actividad de una peticion
def analizar_actividad(cam1, datosPeticion, datosZona, foto1, datosParametrizacion,colorLED='AZUL'):
    intentos = 0
    sec_foto = 0
    detecciones = 0
    if not os.path.exists(cfg['RUTAS']['videos'] + 'ras'+datosPeticion['VS2RAS']):
        os.makedirs(cfg['RUTAS']['videos'] + 'ras'+datosPeticion['VS2RAS'])
    FILE_OUTPUT = cfg['RUTAS']['videos'] + 'ras'+datosPeticion['VS2RAS']+'/C' + datosPeticion['VS2PIC'] + '.mp4'
    if os.path.isfile(FILE_OUTPUT):
        os.remove(FILE_OUTPUT)
    fourcc = cv2.VideoWriter_fourcc(*'mp4v')
    out = cv2.VideoWriter(FILE_OUTPUT, fourcc, 8, (int(cam1.width), int(cam1.height)))
    framesTotales = deepcopy(cam1.Q)
    framesUSB = ''
    maxCROI = 0

    # crearVideoPrevio(cam1,out,out2)
    while intentos <= datosZona['maximo_intentos']:
        intentos = intentos + 1
        sec_foto = sec_foto + 1
        foto2, ret = Hacer_foto(cam1, datosPeticion, sec_foto + 1)
        foto2 = Balizar_foto(foto2, datosPeticion, intentos, 'SI', cam1.scale_percent, datosParametrizacion)
        out.write(foto2)
        framesTotales.append(foto2)
        zonaDetectada = ''
        for z in datosZona:
            if z.find("xy") >= 0:
                if z.find('chg') == -1:
                    zona = z[0:2]
                    zchg = z[2:4]
                    
                    x1 = int(datosZona[z][0] * (cam1.scale_percent / 100))
                    y1 = int(datosZona[z][1] * (cam1.scale_percent / 100))
                    x2 = int(x1 + datosZona[z][2] * (cam1.scale_percent / 100))
                    y2 = int(y1 + datosZona[z][3] * (cam1.scale_percent / 100))
                    fu1 = foto1[y1:y2, x1:x2]
                    fu2 = foto2[y1:y2, x1:x2]
                    
                    err = 0
                    try:
                        err = np.sum((fu1.astype("float") - fu2.astype("float")) ** 2)
                        err /= float(fu1.shape[0] * fu1.shape[1])
                    except:
                        graba_log('error', 'No hay imagen para comprobar')
                    if (err > maxCROI):
                        maxCROI = err
                    if err >= datosZona['umbralPropio']:
                        print('Detectado POS: ', zona, ' CROI: ', err, ' Iter: ', intentos)
                        datosZona[z+'chg'] = datosZona[z+'chg'] + 1
                        detecciones = detecciones + 1
        if datosZona[datosPeticion['VS2POS'] + 'bxychg'] == cfg['PARAMETROS']['intentosValidacion']:
            zonaDetectada = datosZona[datosPeticion['VS2POS'] + 'bxy']
            break
        elif datosZona[datosPeticion['VS2POS'] + 'cxychg'] == cfg['PARAMETROS']['intentosValidacion']:
            zonaDetectada = datosZona[datosPeticion['VS2POS'] + 'cxy']
            break
        elif datosZona[datosPeticion['VS2POS'] + 'dxychg'] == cfg['PARAMETROS']['intentosValidacion']:
            zonaDetectada = datosZona[datosPeticion['VS2POS'] + 'dxy']
            break
        elif datosZona[datosPeticion['VS2POS'] + 'exychg'] == cfg['PARAMETROS']['intentosValidacion']:
            zonaDetectada = datosZona[datosPeticion['VS2POS'] + 'exy']
            break
        intentos = intentos + 1
        time.sleep(0.1)

    out.release()

    # Inerpretacion de las detecciones
    # Caso 1 No ha habido deteccion en la zona principal
    
    if zonaDetectada == '':
        if(cfg['LED']['hayLED'] == 1):
            if(cfg['LED']['apagarFinAccion'] == 1):
                encender_display(cursor,datosZona['display'],datosPeticion['VS2RAS'],True)
        grabCompro = threading.Thread(target=grabar_compro, args=(
            intentos, cam1, datosPeticion, datosParametrizacion, sec_foto, 1, framesTotales, framesUSB))
        grabCompro.start()
        devolver_resultado(datosPeticion, 'NO_DETECTADO', maxCROI,colorLED)
    else:
        if(cfg['LED']['hayLED'] == 1):
            if(cfg['LED']['apagarFinAccion'] == 1):
                apagar_display(cursor,datosZona['display'])
        grabCompro = threading.Thread(target=grabar_compro, args=(
            intentos, cam1, datosPeticion, datosParametrizacion, sec_foto, 0, framesTotales, framesUSB))
        grabCompro.start()
        devolver_resultado(datosPeticion, 'DETECTADO', maxCROI,colorLED)


def grabar_compro(intentos, cam1, datosPeticion, datosParametrizacion, sec_foto, resultado, framesTotales, framesUSB):
    print('Iniciando grabacion de comprobacion del PIC:' + str(datosPeticion['VS2PIC']))
    tmpGbr = cfg['PARAMETROS']['tiempoOK']
    if (resultado == 1):
        tmpGbr = cfg['PARAMETROS']['tiempoPost']
    for i in range(0, tmpGbr, 1):
        foto2, ret = Hacer_foto(cam1, datosPeticion, sec_foto + i + 1)
        if (resultado == 0):
            marcar_resultado(foto2, 'DETECTADO', datosPeticion, datosParametrizacion, cam1.scale_percent)
        else:
            marcar_resultado(foto2, 'NO_DETECTADO', datosPeticion, datosParametrizacion, cam1.scale_percent)
        framesTotales.append(foto2)
        time.sleep(0.1)

    # check if folder exists
    
    
    FILE_OUTPUT2 = cfg['RUTAS']['videos'] + 'ras'+datosPeticion['VS2RAS']+'/T' + datosPeticion['VS2PIC'] + '.mp4'
    fourcc2 = cv2.VideoWriter_fourcc(*'AVC1')
    out2 = cv2.VideoWriter(FILE_OUTPUT2, fourcc2, 10, (int(cam1.width), int(cam1.height)))
    i = 0
    while i < len(framesTotales):
        out2.write(framesTotales[i])
        i = i + 1
    out2.release()
    print('Fin grabacion del PIC:' + str(datosPeticion['VS2PIC']))


def devolver_resultado(datosPeticion, resultado, ROI,colorLED = 'AZUL'):
    res = 0
    tiempo = time.strftime("%y%m%d%H%M%S")
    tmpfin = '20' + tiempo[:2] + '-' + tiempo[2:4] + '-' + tiempo[4:6] + ' ' + tiempo[6:8] + ':' + tiempo[
                                                                                                   8:10] + ':' + tiempo[
                                                                                                                 10:12]
    if resultado == 'NO_DETECTADO':
        res = 1
        sql = "update peticiones set momento_fin='" + tmpfin + "',errores=9998,CROI=" + str(
            ROI) + " where pic='" + datosPeticion['VS2PIC'] + "'"
    else:
        res = 0
        sql = "update peticiones set momento_fin='" + tmpfin + "',errores=0,CROI=" + str(ROI) + " where pic='" + datosPeticion['VS2PIC'] + "'"

    cursor.execute(sql)
    sql = f"UPDATE PARAMETRIZACION SET ULT_COLOR = '{colorLED}' WHERE RAMPA = '{datosPeticion['VS2RAS']}'"
    cursor.execute(sql)
    conn.commit()
    
    if (cfg['INTERFACE']['hayInterface'] == True):
        # ternary expresision
        print('Enviando resultado a la interfaz')
        resultado_para_interface = 'OK' if res == 0 else 'KO'
        data = {
            "ParcelId": datosPeticion['VS2PIC'], 
            "ChuteId": datosPeticion['VS2RAS'],                 
            "CheckState":resultado_para_interface,            
            "CheckTime":datetime.now().strftime("%Y-%m-%dT%H:%M:%S"),
            "VideoURL": '/ras'+datosPeticion['VS2RAS']+'/T' + datosPeticion['VS2PIC'] + '.mp4',
            } 
        
        try:
            response = requests.post(cfg['INTERFACE']['rutaResultado'], json=data)
            print(response.text)
        except Exception as e:
            print(e)
            print(response.text)
            graba_log('interface', 'Error en la interfaz\n' + str(e))
    else:
        print('No hay interfaz configurada') 

    # Elimina registros de vsacada implicados en la accion


def Hacer_foto(cam1, datosPeticion, veces):
    global total_fotos

    lecturas = 0
    ret = cam1.grabbed
    fcamz = deepcopy(cam1.frame)
    if ret == False:
        lecturas = lecturas + 1
        graba_log('errores', 'No hay foto')
    # if ret == True:
    # if veces%2==0 or veces==0:
    # total_fotos=total_fotos+1
    # cv2.imwrite(filename, cv2.resize(fcamz,None,fx=0.8, fy=0.8, interpolation = cv2.INTER_CUBIC))

    return (fcamz, ret)


# Marcar no detectado
def marcar_resultado(foto2, resultado, datosPeticion, datosParametrizacion, escala):
    font = cv2.FONT_HERSHEY_SIMPLEX
    escala = escala / 100
    tamano_fuente = 1 * escala
    # Actualiza registros de peticiones implicados en la accion
    ctx = datosParametrizacion['cuadro_texto_x']
    cty = datosParametrizacion['cuadro_texto_y']
    ctw = datosParametrizacion['cuadro_texto_w']
    cth = datosParametrizacion['cuadro_texto_h']

    if resultado == 'NO_DETECTADO':
        cv2.rectangle(foto2, (int(ctx * escala), int(cty * escala)),
                      (int(ctx * escala) + int(ctw * escala), int(cty * escala) + int(cth * escala)), (0, 0, 255), -1,
                      cv2.LINE_AA)
        cv2.putText(foto2, 'NO DETECTADO:' + datosPeticion['VS2POS'],
                    (int((ctx + 10) * escala), int((cty + 50) * escala)), font, tamano_fuente, (0, 0, 0), 1,
                    cv2.LINE_AA)
        cv2.putText(foto2, 'PIC: ' + datosPeticion['VS2PIC'], (int((ctx + 10) * escala), int((cty + 170) * escala)),
                    font, tamano_fuente, (0, 0, 0), 2, cv2.LINE_AA)

    else:
        cv2.rectangle(foto2, (int(ctx * escala), int(cty * escala)),
                      (int(ctx * escala) + int(ctw * escala), int(cty * escala) + int(cth * escala)), (0, 255, 0), -1,
                      cv2.LINE_AA)
        cv2.putText(foto2, 'DETECTADO en posicion: ' + datosPeticion['VS2POS'],
                    (int((ctx + 10) * escala), int((cty + 50) * escala)), font, tamano_fuente, (0, 0, 0), 1,
                    cv2.LINE_AA)
        cv2.putText(foto2, 'PIC: ' + datosPeticion['VS2PIC'], (int((ctx + 10) * escala), int((cty + 170) * escala)),
                    font, tamano_fuente, (0, 0, 0), 2, cv2.LINE_AA)


# Crea tabla de peticiones con todos los pic de las cajas levantadas


def limpiarVideos(dias, rutaVideos):
    while True:
        print("Limpiando videos antiguos de todas las rampas")
        hoy = time.time()
        path = rutaVideos
        file_list = []
        for folder in (os.listdir(path)):
            for filename in os.listdir(path + '\\' + folder):
                try:
                    if (os.stat(path + '\\' + folder + '\\' + filename).st_mtime < hoy - dias * 86400):
                        os.remove(path + '\\' + folder + '\\' + filename)
                except OSError as e:
                    graba_log('config', 'Fichero no encontrado para eliminar: ' + filename)
        print("Limpieza finalizada.")
        time.sleep(20000)


def keepAlive(conn):
    print('Keep alive on')
    cursorKeepAlive = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
    contador = 120
    while True:
        if contador >= 120:
            sql = f"UPDATE LOG_MOTORES SET MOMENTO = CURRENT_TIMESTAMP WHERE PROCESO = 'VISUALCHECK'"
            cursorKeepAlive.execute(sql)
            contador = 0
            conn.commit()
        contador = contador +1
        fechaHora = time.strftime("%Y%m%d%H%M%S")
        graba_log('keepalive', fechaHora)
        time.sleep(0.8)



# Balizar foto
def Balizar_foto(foto, datosPeticion, veces, balizar, escala, datosParametrizacion):
    if balizar == "SI":
        escala = escala / 100
        font = cv2.FONT_HERSHEY_SIMPLEX
        foto = deepcopy(foto)
        cv2.putText(foto, str(datosPeticion['strtiempo']) + ' Secuencia:' + str(veces), (2, 14), font, 0.55, (0, 255, 0), 1, cv2.LINE_AA)
        sql = f"select * from zonas where zona='{datosPeticion['VS2POS']}' and ras='{datosPeticion['VS2RAS']}'"
        cursor.execute(sql)
        resultadosBalizar = cursor.fetchall()
        for rowBalizar in resultadosBalizar:
            if (rowBalizar['cajas_act'] < rowBalizar['cajas_ext']):

                cv2.rectangle(foto, (int(rowBalizar['x_roi'] * escala), int(rowBalizar['y_roi'] * escala)), (
                    (int(rowBalizar['x_roi'] * escala) + int(rowBalizar['w_roi'] * escala)),
                    int(rowBalizar['y_roi'] * escala) + int(rowBalizar['h_roi'] * escala)), (0, 0, 255), 2, cv2.LINE_AA)
                cv2.rectangle(foto, (int(rowBalizar['x_roi2'] * escala), int(rowBalizar['y_roi2'] * escala)), (
                    (int(rowBalizar['x_roi2'] * escala) + int(rowBalizar['w_roi2'] * escala)),
                    int(rowBalizar['y_roi2'] * escala) + int(rowBalizar['h_roi2'] * escala)), (0, 0, 255), 2, cv2.LINE_AA)
                cv2.rectangle(foto, (int(rowBalizar['x_roi3'] * escala), int(rowBalizar['y_roi3'] * escala)), (
                    (int(rowBalizar['x_roi3'] * escala) + int(rowBalizar['w_roi3'] * escala)),
                    int(rowBalizar['y_roi3'] * escala) + int(rowBalizar['h_roi3'] * escala)), (0, 0, 255), 2, cv2.LINE_AA)
                cv2.rectangle(foto, (int(rowBalizar['x_roi4'] * escala), int(rowBalizar['y_roi4'] * escala)), (
                    (int(rowBalizar['x_roi4'] * escala) + int(rowBalizar['w_roi4'] * escala)),
                    int(rowBalizar['y_roi4'] * escala) + int(rowBalizar['h_roi4'] * escala)), (0, 0, 255), 2, cv2.LINE_AA)
            else:
                cv2.rectangle(foto, (int(rowBalizar['x_roi_ext'] * escala), int(rowBalizar['y_roi_ext'] * escala)), (
                    (int(rowBalizar['x_roi_ext'] * escala) + int(rowBalizar['w_roi_ext'] * escala)),
                    int(rowBalizar['y_roi_ext'] * escala) + int(rowBalizar['h_roi_ext'] * escala)), (255, 0,), 2, cv2.LINE_AA)
                cv2.rectangle(foto, (int(rowBalizar['x_roi2'] * escala), int(rowBalizar['y_roi2_ext'] * escala)), (
                    (int(rowBalizar['x_roi2_ext'] * escala) + int(rowBalizar['w_roi2_ext'] * escala)),
                    int(rowBalizar['y_roi2_ext'] * escala) + int(rowBalizar['h_roi2_ext'] * escala)), (255, 0,), 2, cv2.LINE_AA)
                cv2.rectangle(foto, (int(rowBalizar['x_roi3'] * escala), int(rowBalizar['y_roi3_ext'] * escala)), (
                    (int(rowBalizar['x_roi3_ext'] * escala) + int(rowBalizar['w_roi3_ext'] * escala)),
                    int(rowBalizar['y_roi3_ext'] * escala) + int(rowBalizar['h_roi3_ext'] * escala)), (255, 0,), 2, cv2.LINE_AA)
                cv2.rectangle(foto, (int(rowBalizar['x_roi4_ext'] * escala), int(rowBalizar['y_roi4_ext'] * escala)), (
                    (int(rowBalizar['x_roi4_ext'] * escala) + int(rowBalizar['w_roi4_ext'] * escala)),
                    int(rowBalizar['y_roi4_ext'] * escala) + int(rowBalizar['h_roi4_ext'] * escala)), (255, 0,), 2, cv2.LINE_AA)
            cv2.rectangle(foto, (int(rowBalizar['x'] * escala), int(rowBalizar['y'] * escala)), (
                (int(rowBalizar['x'] * escala) + int(rowBalizar['w'] * escala)), int(rowBalizar['y'] * escala) + int(rowBalizar['h'] * escala)),
                          (255, 255, 255), 2, cv2.LINE_AA)
            cv2.putText(foto, datosPeticion['VS2POS'], (int(rowBalizar['x_baliza'] * escala), int(rowBalizar['y_baliza'] * escala)),
                        font, float(rowBalizar['font_baliza']), (0, 255, 0), 1, cv2.LINE_AA)
            foto = cv2.line(foto, (int(datosParametrizacion['origen_linea_x'] * escala),
                                   int(datosParametrizacion['origen_linea_y'] * escala)),
                            (int(rowBalizar['x_baliza'] * escala), int(rowBalizar['y_baliza'] * escala)), (0, 255, 0), 2)

    return (foto)


def graba_log(archivo, texto):
    fechaHora = time.strftime("%d/%m/%Y %H:%M:%S")
    if (archivo != 'config' and archivo != 'keepalive'):
        try:
            log = open(cfg['logs'] + archivo + '.log', 'a+')
            log.write(fechaHora + ' -- ' + texto + '\n')
            log.close()
        except Exception as e:
            print('No se pudo abrir el fichero de log')
            print(e)
    elif (archivo == 'config'):
        try:
            log = open(archivo + '.log', 'a+')
            log.write(fechaHora + ' -- ' + texto + '\n')
            log.close()
        except:
            print('No se pudo abrir el fichero de configuracion ')
    elif (archivo == 'keepalive'):
        try:
            log = open('C:\\VANDERLANDE\\visual_check.tm', 'w')
            log.write(texto + '\n')
            log.close()
        except Exception as e:
            pass


def limpieza_db():
    cursor = conn.cursor()
    d = datetime.today() - timedelta(days=cfg['PARAMETROS']['diasLimpiezaDB'])
    sql = f"DELETE FROM peticiones WHERE momento_inicio < '{d.strftime('%Y-%m-%d')}'"
    cursor.execute(sql)
    conn.commit()
    print('Limpieza de base de datos realizada')



def apagar_posiciones_anteriores(cursor,ras):
    NUM_POSICIONES = 2
    vueltas = 1
    # BUSCA LA ULTIMAS POSICIONES EN LA TABLA PETICIONES PARA LA RAMPA Y APAGA EL TERCER REGISTRO
    sql = f"SELECT A.ZONA,display_ptl,MOMENTO_INICIO FROM PETICIONES A LEFT JOIN ZONAS B ON A.RAS = B.RAS AND A.ZONA = B.ZONA WHERE A.RAS = '{ras}' ORDER BY MOMENTO_INICIO DESC LIMIT {NUM_POSICIONES}"
    cursor.execute(sql)
    for pic in cursor.fetchall():
        if vueltas == NUM_POSICIONES:
            apagar_display(cursor,pic[1])
        vueltas = vueltas + 1


def encender_display(cursor, iddisplay,ras,hayError = False):
    s = socket.socket()
    colores_ptl = {'ROJO': '000,255,000', 'VERDE': '000,000,100', 'AZUL': '100,000,000', 'AMARILLO': '000,153,153',
                       'ROSA': '255,180,105', 'BLANCO': '160,160,160', 'MORADO': '128,128,000',"ORO":'000,153,153'}
    
    # Selecciona el color del LED anterior de la base de datos
    if hayError == False:
        colorEnviado = 'AZUL'
        sql = f"SELECT ULT_COLOR FROM PARAMETRIZACION WHERE RAMPA = '{ras}'"
        cursor.execute(sql)
        color = cursor.fetchone()
        if color is not None:
            if color[0] == 'AZUL':
                colorEnviado = 'VERDE'
            elif color[0] == 'VERDE':
                colorEnviado = 'ROSA'
            elif  color[0] == 'ROSA':
                colorEnviado = 'AZUL'
    else:
        colorEnviado = 'ROJO'
        
    colorCodigo = colores_ptl[colorEnviado]
    sql = f"SELECT IP,PUERTO,LED_DESDE,LED_HASTA,LED_TIRA FROM LED A LEFT JOIN LED_CONTROL B ON A.CONTROLADOR = B.CONTROLADOR WHERE IDDISPLAY = '{iddisplay}'"
    cursor.execute(sql)
    try:
        direccion_ip,puerto,led_desde,led_hasta,tira_led = cursor.fetchone()
        if led_desde is not None:
            tira_led = str(tira_led).rjust(2,'0')
            led_desde = str(led_desde).rjust(3, '0')
            led_hasta = str(led_hasta).rjust(3, '0')
            intermitente = '0'
            cmd = '1:'+tira_led+':'+led_desde+':'+led_hasta+':'+colorCodigo+':'+intermitente+'|'
            try:
                if(cfg['LED']['modo'] == 'TEST'):
                    graba_log('LED_TEST', cmd )
                    return True,colorEnviado
                else:
                    s.settimeout(2)
                    s.connect((direccion_ip, int(puerto)))
                    s.sendall(cmd.encode('utf-8'))
                    respuesta = s.recv(128)
                    s.close()
                    print(f"Comando enviado: {cmd} - Direccion IP {direccion_ip} - Puerto {puerto}" )
                    if(respuesta == 'ACK|'):
                        return True,colorEnviado
            except Exception as e:
                traceback.print_exc()
                graba_log('socket','Fallo en conexion socket. IP: '+direccion_ip+' | ID Display: '+iddisplay+str(e))
                return False,colorEnviado
        else:
            graba_log('config_led', 'No se encuentra posicion para ese LED')
            return False,colorEnviado
    except:
        graba_log('config_led', 'No se encuentra posicion para esa posicion'+iddisplay)

    return True,colorEnviado
def apagar_display_con_delay(cursor,iddisplay,delay):
    time.sleep(delay)
    apagar_display(cursor,iddisplay)

def apagar_display(cursor,iddisplay):
    s = socket.socket()
    cursor.execute("SELECT ip,puerto,led_desde,led_hasta,led_tira FROM LED A LEFT JOIN LED_CONTROL B ON A.CONTROLADOR = B.CONTROLADOR WHERE IDDISPLAY = %s",
        (iddisplay,))
    try:
        direccion_ip, puerto, led_desde, led_hasta, tira_led = cursor.fetchone()
        if led_desde is not None:
            tira_led = str(tira_led).rjust(2, '0')
            led_desde = str(led_desde).rjust(3, '0')
            led_hasta = str(led_hasta).rjust(3, '0')
            cmd = '2:' + tira_led + ':' + led_desde + ':' + led_hasta + '|'
            try:
                if(cfg['LED']['modo'] == 'TEST'):
                    graba_log('LED_TEST', cmd + ' <---> ' + 'OFF')
                    return True
                else:
                    s.settimeout(2)
                    s.connect((direccion_ip, int(puerto)))
                    s.sendall(cmd.encode('utf-8'))
                    respuesta = s.recv(128).decode("utf-8")
                    s.close()
                    if (respuesta == 'ACK|'):
                        return True
            except Exception as e:
                traceback.print_exc()
                graba_log('socket', 'Fallo en conexion socket. IP: ' + direccion_ip + ' | ID Display: '+iddisplay)
                return False
        else:
            graba_log('config_led', 'No se encuentra posicion para ese LED')
            return False
    except:
        graba_log('config_led', 'No se encuentra posicion para esa posicion' + iddisplay)

def reiniciar_tiras_led(cursor):
    s = socket.socket()
    cursor.execute("SELECT DIRECCION_IP,PUERTO,LED_TIRA FROM LED A LEFT JOIN LED_CONTROL B ON A.CONTROLADOR = B.ID_CONTROLADOR GROUP BY DIRECCION_IP,PUERTO,LED_TIRA")
    for tira_led in cursor.fetchall():
        cmd = f"RST:{str(tira_led[2]).rjust(2, '0')}:RESET"
        s.settimeout(2)
        s.connect((tira_led[0], int(tira_led[1])))
        s.settimeout(None)
        s.sendall(cmd.encode('utf-8'))
        respuesta = s.recv(128).decode("utf-8")
        s.close()
        if (respuesta == 'ACK:RESET'):
            return True

################### COMIENZO DEL PROGRAMA ################


try:
    jsonConfig = open('config.json')
    cfg = json.load(jsonConfig)
    jsonConfig.close()
except Exception as e:
    graba_log('config', 'Error al abrir o parsear el JSON de configuracion')
    sys.exit(1)

try:
    db = cfg['db']
    conn = psycopg2.connect(db)
    cursor = conn.cursor(cursor_factory=psycopg2.extras.DictCursor)
except:
    graba_log('config', 'Error al abrir la base de datos SQLite')
    sys.exit(1)
if conn is not None:
    graba_log('start', 'Inicio de programa')
    # Parametrización de la rampa


    
    sql = "UPDATE PETICIONES SET ERRORES = 9996 WHERE ERRORES IS NULL"
    cursor.execute(sql)
    

    camaras = []
    # Inicio de camaras IP

    sql = "SELECT * FROM CAMARAS"
    cursor.execute(sql)
    camarasSql = cursor.fetchall()
    for camara in camarasSql:
        #rtsp protocol
        rtsp_url = 'rtsp://'+camara['usuario'] + ':' + camara['passwd'] + '@' + camara['ip']
        rtsp_url = camara['rtsp_url']
        camaraObj = VideoGet(rtsp_url,camara['idcamara']).start()
        camaras.append(camaraObj)
        titulo = 'Camara'+str(camara['idcamara'])+'- '+camara['ip']
        VideoShow(camaraObj,titulo).start()

    # Limpieza de Fotogramas Antiguos
    # hilofotos = threading.Thread(target=limpiarFotos, args=(ras,diasLimpiezaFotos,rutaFotos))
    # hilofotos.start()


    

    keepalivet = threading.Thread(target=keepAlive,args=(conn,))
    keepalivet.start()
    hilovideos = threading.Thread(target=limpiarVideos, args=(cfg['PARAMETROS']['diasLimpiezaVideos'], cfg['RUTAS']['videos']))
    hilovideos.start()
    hilodb = threading.Thread(target=limpieza_db)
    hilodb.start()
    
    aux.borra_pid('recepcion.pid')
    pid = str(os.getpid())
    aux.graba_pid('recepcion.pid', pid)

    if len(camaras) > 0:
        if pid != aux.recupera_pid('recepcion.pid'):
            sys.exit(1)
        try:
            sql = f"SELECT RAMPA FROM PARAMETRIZACION WHERE RAMPA IS NOT NULL AND RAMPA <> ''"
            cursor.execute(sql)
            rampas = cursor.fetchall()
            for rampa in rampas:
                threading.Thread(target=Peticiones,args=(conn, camaras,rampa[0])).start()
        except Exception as e:
            graba_log('peticiones', 'Excepcion al iniciar la comprobacion\n' + str(e))
            traceback.print_exc()
    else:
        sys.exit(1)

