
import time
import json
import sys
import socket
import requests
import random
import subprocess

def graba_pid(archivo,texto):
    try:
        log = open(cfg['logs']+archivo,'w+')
        log.write(texto)
        log.close()
    except Exception as e:
        print('No se pudo escribir el proceso')
        print(str(e))

def borra_pid(archivo):
    try:
        log = open(cfg['logs']+archivo,'r+')
        pid = log.readline()
        #os.kill(int(pid), signal.SIGTERM)
        subprocess.check_output("Taskkill /PID %s /F /t" % pid)
        log.close()
    except Exception as e:
        print('No se pudo borrar el proceso')
        print(str(e))

def recupera_pid(archivo):
    try:
        log = open(cfg['logs']+archivo,'r+')
        pid = log.readline()
        return pid
    except Exception as e:
        print('No se pudo borrar el proceso')
        print(str(e))


def graba_log_plano(archivo,texto):
    fechaHora = time.strftime("%d/%m/%Y %H:%M:%S")
    try:
        log = open(cfg['logs']+archivo+'.log','a+')
        log.write(texto+'\n')
        log.close()
    except Exception as e:
        print('No se pudo abrir el fichero de log')
        print(e)
def graba_log(archivo,texto):
    fechaHora = time.strftime("%d/%m/%Y %H:%M:%S")
    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)
def graba_log_json(archivo,texto):
    fechaHora = time.strftime("%d/%m/%Y %H:%M:%S")
    try:
        log = open(cfg['interfaces']['rutaHistoricoRecepcion']+'\\'+archivo+'.json','w+')
        log.write(texto)
        log.close()
    except Exception as e:
        print('No se pudo abrir el fichero de log')
        print(e)
def graba_log_agv(cursor,orden,error,peticion, respuesta):
    sql = f"INSERT INTO AGV_ERROR VALUES ({orden},'{peticion}','{respuesta}','PE','{error}',CURRENT_TIMESTAMP)"
    cursor.execute(sql)
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)


def encender_display(cursor, estacion):
    accion = estacion[7]
    iddisplay = estacion[3]
    s = socket.socket()
    if(apagar_display(cursor,estacion) or 1 == 1):
        #BRG
        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'}
        cursor.execute("SELECT TIPOCFG, VALORALFA1,VALORALFA2 FROM CONFIGURACION WHERE TIPOCFG = :ACC", (accion,))
        config_led = cursor.fetchone()
        if config_led is not None:
            color = colores_ptl[config_led[1]]
            intermitente = config_led[2]
            if intermitente == 'FIJO':
                intermitente = '0'
            elif intermitente == 'INTERMITENTE':
                intermitente = '1'
            cursor.execute("SELECT direccion_ip,puerto FROM LED_CONTROL WHERE PUESTO = :PUESTO",(estacion[0],))
            direccion_ip,puerto = cursor.fetchone()
            cursor.execute("SELECT LED_TIRA,LED_DESDE,LED_HASTA FROM LED WHERE IDDISPLAY = :DISPLAY", (iddisplay,))
            pos_led = cursor.fetchone()
            if pos_led is not None:
                tira_led = str(pos_led[0]).rjust(2,'0')
                led_desde = str(pos_led[1]).rjust(3, '0')
                led_hasta = str(pos_led[2]).rjust(3, '0')
                cmd = '1:'+tira_led+':'+led_desde+':'+led_hasta+':'+color+':'+intermitente+'|'
                try:
                    modo = 'NTEST'
                    if(modo == 'TEST'):
                        graba_log('LED_TEST', cmd + ' <---> '+accion)
                        return True
                    else:
                        s.settimeout(3)
                        s.connect((direccion_ip, puerto))
                        s.sendto(str(cmd).encode('utf-8'),(direccion_ip, puerto))
                        respuesta = s.recv(1024)
                        s.close()
                        return True
                except Exception as e:
                    graba_log('socket','Fallo en conexion socket. IP: '+direccion_ip+' | Estacion: '+estacion[0]+' Excepcion:'+str(e))
                    return False
            else:
                graba_log('config_led', 'No se encuentra posicion para ese LED')
                return False
        else:
            graba_log('config','No se encuentra configuracion para esa accion' + accion)
            return False
    else:
        graba_log('led', 'No se pudo apagar el LED.')
        return False
    return True
def apagar_display(cursor,estacion):
    iddisplay = estacion[3]
    s = socket.socket()
    cursor.execute("SELECT direccion_ip,puerto FROM LED_CONTROL WHERE PUESTO = :PUESTO", (estacion[0],))
    direccion_ip, puerto = cursor.fetchone()
    cursor.execute("SELECT LED_TIRA,LED_DESDE,LED_HASTA FROM LED WHERE IDDISPLAY = :DISPLAY", (iddisplay,))
    pos_led = cursor.fetchone()
    if pos_led is not None:
        tira_led = str(pos_led[0]).rjust(2, '0')
        led_desde = str(pos_led[1]).rjust(3, '0')
        led_hasta = str(pos_led[2]).rjust(3, '0')
        if(estacion[8] == 'EXP' or estacion[8] == 'PCK'):
            cmd = '2:' + tira_led + ':' + led_desde + ':' + led_hasta + '|'
        else:
            cmd = '9:' + tira_led +'|'
        try:
            modo = 'NTEST'
            if (modo == 'TEST'):
                graba_log('LED_TEST', cmd + ' <---> ' + 'OFF')
                return True
            else:
                s.settimeout(3)
                s.connect((direccion_ip, puerto))
                s.sendto(str(cmd).encode('utf-8'),(direccion_ip, puerto))
                respuesta = s.recv(1024)
                s.close()
                return True
        except Exception as e:

            graba_log('socket','Fallo en conexion socket. IP: '+direccion_ip+' | Estacion: '+estacion[0]+' Excepcion:'+str(e))
            return False
    else:
        graba_log('config_led', 'No se encuentra posicion para ese LED')
        return False
def reiniciar_estacion(cursor,estacion):
    iddisplay = estacion[3]
    s = socket.socket()
    cursor.execute("SELECT direccion_ip,puerto FROM LED_CONTROL WHERE PUESTO = :PUESTO", (estacion[0],))
    direccion_ip, puerto = cursor.fetchone()
    cmd = 'Z:|'
    try:
        modo = 'NTEST'
        if (modo == 'TEST'):
            graba_log('LED_TEST', cmd + ' <---> ' + 'OFF')
            return True
        else:
            s.settimeout(3)
            s.connect((direccion_ip, puerto))
            s.sendto(str(cmd).encode('utf-8'),(direccion_ip, puerto))
            respuesta = s.recv(1024)
            s.close()
            return True
    except Exception as e:
        graba_log('socket', 'Fallo en conexion socket. IP: ' + direccion_ip + ' | Estacion: ' + estacion[0]+' '+str(e))
        return False
    else:
        graba_log('config_led', 'No se encuentra posicion para ese LED')
        return False
def encender_leds_estaciones(cursor, estaciones):
    return True
    resultado = False
    for cod_estacion in estaciones:
        estacion = estaciones[cod_estacion]
        if(encender_display(cursor,estacion)):
            resultado = True
        else:
            resultado = False
    return resultado
def encender_leds_estaciones_sin_entrada(cursor, estaciones):
    resultado = False
    for cod_estacion in estaciones:
        estacion = estaciones[cod_estacion]
        estacion = list(estacion)
        if(estacion[8] == 'ENT'):
            estacion[6] = 'SIN_ENTRADA'
            estacion[7] = 'SIN_ENTRADA'
            estacion = tuple(estacion)
            if(encender_display(cursor,estacion)):
                resultado = True
    return resultado
def reiniciar_leds_estacion(cursor, estaciones, estacionApagar):
    resultado = False
    estacionesApagar = dict(estaciones)
    for cod_estacion in estaciones:
        estacion = estaciones[cod_estacion]
        if(estacion[0] != estacionApagar):
            estacionesApagar.pop(estacion[0]+'_'+estacion[1])
    reiniciar_leds_estaciones(cursor,estacionesApagar)
    cursor.execute(f"UPDATE PUESTOS SET ACCION = ' ' WHERE PUESTO = '{estacionApagar}'")
    return resultado
def recupera_codigo_peticion(cursor):
    resultado = False
    estacionesApagar = dict(estaciones)
    cursor.execute(f"UPDATE PUESTOS SET ACCION = ' ' WHERE PUESTO = '{estacionApagar}'")
    return resultado


def ping(host):
    """
    Returns True if host (str) responds to a ping request.
    Remember that a host may not respond to a ping (ICMP) request even if the host name is valid.
    """

    # Option for the number of packets as a function of
    param = '-n' if platform.system().lower()=='windows' else '-c'

    # Building the command. Ex: "ping -c 1 google.com"
    command = ['ping', param, '1', host]

    return subprocess.call(command) == 0
def escribir_estado_agv(cursor,agv):
    resultado = True
    estado = estado_agv(agv['status'],agv['online'])
    bateria = int(agv['battery'])
    punto = agv['posX']+""+agv['mapCode']+""+agv['posY'];
    codigo = agv['robotCode']
    minutos_orden_colgada = 6
    if(estado != 'ERROR' and estado != 'AGV_PARADO'):
        sql = f"SELECT CODIGO_AGV FROM AGV_ERROR_LOG WHERE VECES > 1 AND extract( day from(CURRENT_TIMESTAMP - MOMENTO_ULTIMO)*24*60*60) < 60 AND CODIGO_AGV = '{codigo}'"
        cursor.execute(sql)
        resultado = cursor.fetchone()
        if resultado is None:
            # NO HAY ERROR EN AGV_ERROR_LOG
            sql = f"SELECT RESULTADO_OPERACION FROM ORDENES WHERE ESTADO IN ('1','2','3') AND extract( day from(CURRENT_TIMESTAMP - MULTIMO_MOVIMIENTO)*24*60*60) > {minutos_orden_colgada*60} AND RESULTADO_OPERACION = '{codigo}'"
            cursor.execute(sql)
            resultado = cursor.fetchone()
            if(resultado is None):
                cursor.execute(f"UPDATE AGV SET ESTADO = '{estado}', BATERIA = {bateria}, ULTIMO_PUNTO = '{punto}',HORA_ERROR = CURRENT_TIMESTAMP WHERE CODIGO_AGV = '{codigo}'")
            else:
                print('Tarea tiempo')
                cursor.execute(f"UPDATE AGV SET ESTADO = 'ERROR_TIEMPO', BATERIA = {bateria}, ULTIMO_PUNTO = '{punto}' WHERE CODIGO_AGV = '{codigo}'")
        else:
            #HAY ERROR EN AGV_ERROR_LOG
            cursor.execute(f"UPDATE AGV SET ESTADO = 'ERROR', BATERIA = {bateria}, ULTIMO_PUNTO = '{punto}' WHERE CODIGO_AGV = '{codigo}'")
    else:
        #HAY ERROR EN AGV_ERROR_LOG
        cursor.execute(f"UPDATE AGV SET ESTADO = '{estado}', BATERIA = {bateria}, ULTIMO_PUNTO = '{punto}' WHERE CODIGO_AGV = '{codigo}'")
    return resultado

def buscar_tarea_agv_bloqueado(cursor,orden):
    contenedor = orden['CONTENEDOR']
    sql = f"SELECT SEC_INT,RESULTADO_OPERACION FROM ORDENES WHERE contenedor = {contenedor} and TIPO_OPERACION = 'BL' AND ESTADO = '9'"
    cursor.execute(sql)
    resultado = cursor.fetchone()
    if(resultado is not None):
        return resultado
    else:
        return None

def obtener_contador(cursor,tipo_contador):
    contador = 0
    cursor.execute("select nextval(%s);", [tipo_contador, ])
    res = cursor.fetchone()
    try:
        contador = res['nextval']
    except:
        contador = res[0]
    return contador
def estado_agv(estado,online):
    estadoT = 'ERROR'
    if(online == True):
        if estado in ('1','246','4'):
            estadoT = 'ESPERANDO'
        elif estado in ('2','6'):
            estadoT = 'OCUPADO'
        elif estado in ('151'):
            estadoT = 'RECOLOCANDO'
        elif estado in ('5'):
            estadoT = 'EN PAUSA'
        elif estado in ('81'):
            estadoT = 'AGV_PARADO'
        elif estado in ('7','9'):
            estadoT = 'CARGANDO'
        else:
            #print(estado)
            estadoT = 'ERROR'
    else:
        estadoT = 'DESCONECTADO'
    return estadoT
def reiniciar_leds_estaciones(cursor,estaciones):
    return True
    resultado = False
    for cod_estacion in estaciones:
        estacion = estaciones[cod_estacion]
        if(reiniciar_estacion(cursor,estacion)):
            resultado = True
        else:
            resultado = False
    return resultado
def agv_en_error(codigo):
    return False
def recuperar_informacion_agvs(agv=''):
    data = {
        "reqCode": "MOTOR_INFO_AGV",
        "mapShortName": f"{cfg['MAPA']}"
        }
    url = "http://"+cfg['IP_AGV']+":8182/rcms-dps/rest/queryAgvStatus"
    headers = {'Content-Type':'application/json'}
    try:
        r = requests.post(url,json=data,timeout=2)
        if(r.status_code == 200):
            agvs = json.loads(r.text)
            if(agvs["code"] == '0'):
                return agvs['data']
            else:
                return None
    except Exception as e:
        return None

def priorizar_orden(orden=''):
    data = {
        "reqCode": "PRIO_ORDEN_"+str(orden),
        "priorities": [{
            "priority": "9",
            "taskCode": ""+str(orden)
            }]
        }
    url = "http://"+cfg['IP_AGV']+":8182/rcms/services/rest/hikRpcService/setTaskPriority"
    headers = {'Content-Type':'application/json'}
    r = requests.post(url,json=data)
    if(r.status_code == 200):
        res = json.loads(r.text)
        if(res["code"] == '0'):
            return res
        else:
            return res
def cancelar_orden_fmr(cursor,orden, motivo=''):
    
    url = cfg['API_AGV'] + '/rcms/services/rest/hikRpcService/cancelTask'
    data = {
        "reqCode":"CANCELAR_FMR_"+str(obtener_contador(cursor,'PCO')),
        "forceCancel": '0',
        "matterArea": "",
        "taskCode": orden
    }
    r = requests.post(url,json=data)
    if(r.status_code == 200):
        res = json.loads(r.text)
        if(res["code"] == '0'):
            return res
        else:
            return res
        
        
def pausa_agv(cursor,agv):
    data = {
        "reqCode": "PAUSA_"+str(obtener_contador(cursor,'PCO')),
        "robotCount": 1,
        "robots": [
            agv
        ]
        }
    url = "http://"+cfg['IP_AGV']+":8182/rcms/services/rest/hikRpcService/stopRobot"
    headers = {'Content-Type':'application/json'}
    r = requests.post(url,json=data)
    if(r.status_code == 200):
        res = json.loads(r.text)
        if(res["code"] == '0'):
            return res
        else:
            return res

def continuar_agv(cursor,agv):
    data = {
        "reqCode": "CONTINUAR_"+str(obtener_contador(cursor,'PCO')),
        "robotCount": 1,
        "robots": [
            agv
        ]
        }
    url = "http://"+cfg['IP_AGV']+":8182/rcms/services/rest/hikRpcService/resumeRobot"
    headers = {'Content-Type':'application/json'}
    r = requests.post(url,json=data)
    if(r.status_code == 200):
        res = json.loads(r.text)
        if(res["code"] == '0'):
            return res
        else:
            return res

def recupera_informacion_contenedor(contenedor):
    url = f"{cfg['API_AGV']}/rcms/services/rest/hikRpcService/queryPodBerthAndMat"
    data = {"reqCode": "MOTOR_INFO_RACK_"+str(random.randint(1,100)),"podCode": contenedor}
    headers = {'Content-type': 'application/json'}
    respuesta = requests.post(url, json=data, headers=headers)
    if(respuesta.status_code == 200):
        info_contenedor = json.loads(respuesta.text)
        if(info_contenedor['code'] == "0"):
            info_contenedor = info_contenedor['data'][0]
            return info_contenedor
        else:
            return None
    else:
        return None

def asignar_desasignar_contenedor_a_punto(cursor,contenedor,punto,asignar,orientacion):
    url = f"{cfg['API_AGV']}/rcms/services/rest/hikRpcService/bindPodAndBerth"
    data = {
        "reqCode": "MOTOR_ASIGNAR_RACK_"+str(obtener_contador(cursor,'PCO')),
        "podCode": str(contenedor),
        "positionCode": str(punto),
        "podDir": str(orientacion),
        "indBind": str(asignar)
}
    headers = {'Content-type': 'application/json'}
    respuesta = requests.post(url, json=data, headers=headers)
    if(respuesta.status_code == 200):
        info_contenedor = json.loads(respuesta.text)
        return info_contenedor
    else:
        return None
def asignar_desasignar_palet_a_bin(cursor,contenedor,punto,asignar):
    url = f"{cfg['API_AGV']}/rcms/services/rest/hikRpcService/bindCtnrAndBin"
    data = {
        "reqCode": "MOTOR_ASIGNAR_BIN_"+str(obtener_contador(cursor,'PCO')),
        "stgBinCode": str(punto),
        "ctnrCode": str(contenedor),
        "ctnrType": "1",
        "indBind": str(asignar)
}
    
    headers = {'Content-type': 'application/json'}
    try:
        respuesta = requests.post(url, json=data, headers=headers,timeout=5)
        if(respuesta.status_code == 200):
            info_contenedor = json.loads(respuesta.text)
            return info_contenedor
        else:
            return None
            
    except Exception as e:
        return None
def comprobar_tiempo_barrera(cursor,agv):
    tiempo = 0
    sql = f"SELECT extract( day from(CURRENT_TIMESTAMP - MOMENTO_ULTIMO)*24*60*60) FROM AGV_ERROR_LOG WHERE CODIGO_AGV = '{agv['robotCode']}'"
    cursor.execute(sql)
    resultado = cursor.fetchone()
    if resultado is not None:
        timepo = resultado[0]
    return tiempo
def recupera_informacion_contenedores():
    url = f"{cfg['API_AGV']}/rcms/services/rest/hikRpcService/queryPodBerthAndMat"
    data = {"reqCode": "MOTOR_INFO_RACK_"+str(random.randint(1,100)),"mapShortName": cfg['MAPA_SHORTNAME']}
    headers = {'Content-type': 'application/json'}
    respuesta = requests.post(url, json=data, headers=headers)
    if(respuesta.status_code == 200):
        info_contenedor = json.loads(respuesta.text)
        if(info_contenedor['code'] == "0"):
            info_contenedor = info_contenedor['data']
            return info_contenedor
        else:
            return None
    else:
        return None
    

def bloquear_zona(cursor,zona, modo):
    # MODO-> 0: Desbloquear, 1: Bloquear
    url = f"{cfg['API_AGV']}/rcms/services/rest/hikRpcService/setAreaState"
    data = {
        "reqCode": "MOTOR_BLOQUEO_ZONA_"+str(obtener_contador(cursor,'PCO')),
        "matterArea": 'A'+zona,
        "indBind": str(modo)
        }
    headers = {'Content-type': 'application/json'}
    respuesta = requests.post(url, json=data, headers=headers)
    if(respuesta.status_code == 200):
        return json.loads(respuesta.text)
    else:
        return None