import numpy as np

def calcular_densidade_ar(altitude):
    """
    Calcula a densidade do ar com base na altitude usando a fórmula barométrica.
    altitude em metros. Se altitude for None, assume 0 metros (nível do mar).
    """
    if altitude is None:
        altitude = 0  # Define altitude padrão como 0 se não for fornecido

    # Parâmetros para o cálculo
    T0 = 288.15  # Temperatura ao nível do mar (K)
    L = 0.0065  # Gradiente térmico (K/m)
    p0 = 101325  # Pressão ao nível do mar (Pa)
    R = 287.05  # Constante dos gases para o ar (J/(kg·K))
    g = 9.80665  # Aceleração da gravidade (m/s²)

    # Temperatura a uma dada altitude
    T_h = T0 - L * altitude

    # Pressão a uma dada altitude
    p_h = p0 * (T_h / T0) ** (g / (R * L))

    # Densidade do ar a uma dada altitude
    densidade_ar = p_h / (R * T_h)
    return densidade_ar


def calcular_cargas_termicas_ambiente(termicos):
    """
    Calcula as cargas térmicas do ambiente com base nos dados fornecidos.
    Utiliza a área do piso para ajustar a carga térmica de iluminação e outras fontes.
    """
    # Número de horas para o dia
    horas_dia = 13  # Assume-se um ciclo térmico de 06:00 até 18:00
    # Inicializando arrays para as cargas térmicas
    carga_sensivel_total = np.zeros(horas_dia)
    carga_latente_total = np.zeros(horas_dia)
    carga_iluminacao = np.zeros(horas_dia)
    carga_equipamentos = np.zeros(horas_dia)

    # Carga térmica sensível e latente por pessoa
    carga_sensivel_pessoas = termicos.calor_sensivel_pessoa * termicos.numero_pessoas
    carga_latente_pessoas = termicos.calor_latente_pessoa * termicos.numero_pessoas

    # Carga térmica de iluminação
    carga_iluminacao += termicos.taxa_iluminacao * termicos.area_piso

    # Carga térmica de equipamentos
    dissipacao_equipamentos_horaria = termicos.dissipacao_equipamentos
    carga_equipamentos += np.array([dissipacao_equipamentos_horaria] * horas_dia)

    # Adicionando cargas térmicas totais (ajustando a carga sensível sem somar à carga latente neste momento)
    carga_sensivel_total += carga_sensivel_pessoas + carga_iluminacao + carga_equipamentos
    carga_latente_total += carga_latente_pessoas

    # Resultados finais com arredondamento para duas casas decimais
    carga_sensivel_total = np.round(carga_sensivel_total, 2)
    carga_latente_total = np.round(carga_latente_total, 2)
    carga_iluminacao = np.round(carga_iluminacao, 2)
    carga_equipamentos = np.round(carga_equipamentos, 2)
    carga_sensivel_pessoas = np.round(carga_sensivel_pessoas, 2)
    carga_latente_pessoas = np.round(carga_latente_pessoas, 2)

    return {
        "carga_sensivel_total": carga_sensivel_total,
        "carga_sensivel_total": carga_sensivel_total,
        "carga_latente_total": carga_latente_total,
        "carga_iluminacao": carga_iluminacao,
        "carga_equipamentos": carga_equipamentos,
        "carga_sensivel_pessoas": carga_sensivel_pessoas,
        "carga_latente_pessoas": carga_latente_pessoas,
    }

def calcular_vazao_ar_infiltracao(area_piso, pe_direito, horas_dia=13):
    """
    Calcula a vazão de ar externo devido à infiltração, constante para cada hora do dia.
    """
    vazao_infiltracao = 1.5 * area_piso * pe_direito  # m³/h
    vazao_horaria_infiltracao = np.array([vazao_infiltracao] * horas_dia)
    return vazao_horaria_infiltracao

def calcular_vazao_ar_renovacao(numero_pessoas, taxa_renovacao, horas_dia=13):
    """
    Calcula a vazão de ar externo devido à renovação, constante para cada hora do dia.
    """
    vazao_renovacao = numero_pessoas * taxa_renovacao  # m³/h
    vazao_horaria_renovacao = np.array([vazao_renovacao] * horas_dia)
    return vazao_horaria_renovacao

def calcular_vazao_total_ar_exterior(area_piso, pe_direito, numero_pessoas, taxa_renovacao, horas_dia=13):
    """
    Calcula a vazão total de ar externo (infiltração + renovação) para cada hora do dia.
    """
    vazao_infiltracao_horaria = calcular_vazao_ar_infiltracao(area_piso, pe_direito, horas_dia)
    vazao_renovacao_horaria = calcular_vazao_ar_renovacao(numero_pessoas, taxa_renovacao, horas_dia)
    vazao_total_ar_exterior = vazao_infiltracao_horaria + vazao_renovacao_horaria
    return vazao_total_ar_exterior

def calcular_calor_sensivel_ar_exterior(termicos, temperaturas_externas, temperatura_interna, vazao_total_ar_exterior):
    """
    Calcula o calor sensível devido à vazão de ar exterior em cada hora do dia, com o resultado em W (watts).
    """
    densidade_ar = calcular_densidade_ar(termicos.altitude)  # Densidade do ar ajustada para a altitude
    capacidade_calorifica_ar = 1005  # J/kg°C

    # Calor sensível horário em W
    calor_sensivel = (densidade_ar * capacidade_calorifica_ar * vazao_total_ar_exterior * 
                      (temperaturas_externas - temperatura_interna)) / 3600 
    return calor_sensivel

def calcular_calor_latente_ar_exterior(densidade_ar, vazao_total_ar_exterior, umidade_absoluta_externa, umidade_absoluta_interna, hlv=2440):
    """
    Calcula o calor latente devido à vazão de ar exterior em cada hora do dia, com o resultado em W (watts).
    
    Parâmetros:
    - densidade_ar: Densidade do ar (kg/m³), ajustada para a altitude do projeto.
    - vazao_total_ar_exterior: Vazão total de ar exterior (m³/h).
    - umidade_absoluta_externa: Umidade específica externa (g/kg).
    - umidade_absoluta_interna: Umidade específica interna (g/kg).
    - hlv: Calor latente de vaporização da água (kJ/kg), com valor padrão de 2440 kJ/kg.
    
    Retorna:
    - Calor latente (W).
    """
    # Converter h_lv de kJ/kg para J/kg
    hlv_joules = hlv * 1000  # Convertendo de kJ/kg para J/kg

    # Diferença de umidade específica em kg/kg (conversão de g/kg para kg/kg)
    umidade_absoluta_diferenca = (umidade_absoluta_externa - umidade_absoluta_interna) / 1000

    # Convertendo vazão de ar total de m³/h para m³/s
    if vazao_total_ar_exterior is not None:
        vazao_total_ar_exterior_m3_s = vazao_total_ar_exterior / 3600
    else:
        raise ValueError("A vazão total de ar exterior é None e não pode ser usada no cálculo.")

    # Verificar se densidade_ar é um número e não None
    if densidade_ar is None:
        raise ValueError("A densidade do ar é None e não pode ser usada no cálculo.")

    # Calor latente (Q_L) em W, conforme a equação fornecida
    calor_latente = densidade_ar * vazao_total_ar_exterior_m3_s * hlv_joules * umidade_absoluta_diferenca

    return calor_latente






