from __future__ import division
from pyomo.environ import *
from red.read import excel2net
from red.create import *
from red.create1 import *
from red.makeBdc import makeBdc
from utils.arr2dict import arr2dict
from pyomo.environ import SolverFactory
from pyomo.kernel import value
from numpy import zeros, array
from pandas import DataFrame, ExcelWriter

def setmodel(file):
        
    print("{:=^100}".format(""))
    print("{:^100}".format(" Modelo de Predespacho Regional"))
    print("{:^100}".format(" Mercados Eléctricos de Centroamérica (c) 2020 "))
    print("{:=^100}".format(""))
    # ============================================================================
    # Importación de datos desde archivo Excel
    # ============================================================================

    #Parametros de la linea
    print("Leyendo información de red...")
    net = excel2net(file)
    bus = setbus(net)#Nodos
    branch = setbranch(net, bus)#Set lineas
    bu = branch[:, 5]#potenica max de la linea
    bl = branch[:, 6]#potenica min de la linea
    xc = branch[:,3]#Reactancia de la linea
    rc = branch[:,4]#Resistencia de la linea
    nb = bus.shape[0] #Numero de nodos
    nbr = branch.shape[0]#Numero de lineas
    A = makeBdc(bus, branch)#Matriz incidente
    brnames = branchnames(bus, branch)#Nombre de las lineas
    inc = A.toarray()*-1

    print("Leyendo información de los Despachos nacionales")
    dg=read_D_G(file)
    dem=setvariable(dg['demanda'])
    gen=setvariable(dg['generacion'])

    # Inicio del modelo de optimización
    model=ConcreteModel()

    #sets
    model.i=Set(initialize=range(0, nb))#numero de nodos
    model.c=Set(initialize=range(0, nbr))#Numero de lineas

    #Parametros
    #Parametros de la red
    model.rtmw_min= Param(model.c, initialize=dict(enumerate(bl)))
    model.rtmw_max= Param(model.c, initialize=dict(enumerate(bu)))
    model.Inc = Param(model.c, model.i, initialize=arr2dict(inc))
    model.Xc = Param(model.c, initialize=dict(enumerate(xc)))
    model.Rc = Param(model.c, initialize=dict(enumerate(rc)))
    
    #Parametros de los predespachos nacionales
    model.D = Param(model.i, initialize=dict(enumerate(dem)))
    model.G = Param(model.i, initialize=dict(enumerate(gen)))

    #Variable problema de optimizacion
    model.inyeccion= Var(model.i, domain=NonNegativeReals)#Inyeccion por nodo
    model.retiro= Var(model.i, domain=NonNegativeReals)#Retiro por nodo
    model.ref_angular_nacional= Var(model.i)#Fase del voltaje en el nodo
    model.rtmw_nacional= Var(model.c)#Flujo DC NACIONAL

    print(1)
    def balance_inyeccion_retiro_nacional(model,i):
        return (model.G[i] +  sum(model.Inc[c,i]*model.rtmw_nacional[c] for c in model.c) - # Al dividir entre 100 Rc
        0.5*sum(((model.Inc[c,i]*model.rtmw_nacional[c])**2)*(model.Rc[c]/100) for c in model.c)  # toda la ec. se pasa a p.u.
        == model.D[i])  
    model.balance_inyeccion_retiro_nacional_constraint= Constraint(model.i,rule=balance_inyeccion_retiro_nacional)

    def rtmw_min_restriccion(model,c):
        return (model.rtmw_nacional[c]>=-model.rtmw_min[c])
    model.rtmw_min_constraint= Constraint(model.c, rule=rtmw_min_restriccion)

    def rtmw_max_restriccion(model,c):
        return (model.rtmw_nacional[c]<=model.rtmw_max[c])
    model.rtmw_max_constraint= Constraint(model.c, rule=rtmw_max_restriccion)

    def flujo_potencia_actica_nacional(model,c):
        return ((model.Xc[c])*model.rtmw_nacional[c]+sum(model.Inc[c,i]*model.ref_angular_nacional[i] for i in model.i)== 0)
    model.flujo_potencia_actica_nacional_constraint= Constraint(model.c, rule=flujo_potencia_actica_nacional)

    print("Construcción del modelo terminada.")

    opt = SolverFactory('ipopt')
    #opt.options['max_iter']= 15000
    result = opt.solve(model)
    model.solutions.store_to(result)

    # Construcción de array para grabar
    # =============================================================================
    flujos = brnames.copy()
    f2= array(list(model.rtmw_nacional.get_values().values()))
    perdidas=zeros(nbr)
    for c in model.c:
        perdidas[c]=(f2[c]**2)*rc[c]/100
    flujos['Flujo Nacional']=f2
    flujos['Perdidas Nacionales'] = perdidas

    writer=ExcelWriter("Resultados_predespacho_nacionales.xlsx")
    flujos.to_excel(writer,'IEP-RTR',index=False)
    writer.save()

    print("{:=^100}".format(""))
    print("{:^100}".format(" Script Finalizado "))
    print("{:^100}".format(" Mercados Eléctricos de Centroamérica (c) 2020 "))
    print("{:=^100}".format(""))
    #print(result)
    return 0
