import numpy as np
from flask import Flask, request, jsonify, render_template
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import pandas as pd
import os
import matplotlib.pyplot as plt
from scipy.interpolate import interp1d
from func import  calculate_displacement_and_force, Berry_Eberhard_Buckling_Model, Force_Displacement_Relation, Potential_Deformation_Limit_States, Interaction_Diagram, Concrete_Strain, Steel_Strain, Moment_Curvature_Relation, CURVATURE_RELATION_ITERATIVE_PROCESS_TO_FIND_THE_MOMENT, CORRECTED_AREAS, manderun, manderconf, steelking, Raynor, manderconflw, stress_strain_relations_Confined, stress_strain_relations_Reinforcing_Steel, compute_concrete_layers, compute_rebars, Define_vector, Limit_States, Gross_area_and_steel_ratios, calculate_plastic_hinge, shear_deflection, shear_strength, calculate_moment_capacity    
from pOutput import  mainOut, html_01, html_02, html_03, html_04, html_05, html_07, html_08

app = Flask(__name__)


@app.route('/', methods=['POST', 'GET'])
def hello_world():
    met = request.method
    if request.form:    
        #num1 = request.form.get('num1') 
        #num2 = request.form.get('num2')

        name = request.form.get('name')
        interaction = request.form.get('interaction')

        H = float(request.form.get('H')) 
        B = float(request.form.get('B')) 
        ncx = float(request.form.get('ncx'))    
        ncy = float(request.form.get('ncy'))   
        clb = float(request.form.get('clb'))    

        L = float(request.form.get('L'))                         
        bending = request.form.get('bending')                
        ductilitymode = request.form.get('ductilitymode')        

        MLR = request.form.get('MLR')  
        MLR = MLR.strip()
        MLR = eval(MLR) 
        MLR = np.array(MLR, dtype=float)

        Dh = float(request.form.get('Dh'))                        
        s = float(request.form.get('s'))                         

        P = float(request.form.get('P'))                         

        confined    = request.form.get('confined')  
        unconfined  = request.form.get('unconfined')  
        rebar       = request.form.get('rebar')  
        typ        = request.form.get('typ')             #Ex

        wi = request.form.get('wi')   
        wi = wi.strip()
        wi = eval(wi) 
        wi = np.array(wi, dtype=float)
                                           
        fpc = float(request.form.get('fpc'))                    
        Ec = float(request.form.get('Ec'))                      
        eco = float(request.form.get('eco'))                  
        esm = float(request.form.get('esm'))                   
        espall = float(request.form.get('espall'))              

        fy = float(request.form.get('fy'))                     
        fyh = float(request.form.get('fyh'))                   
        Es = float(request.form.get('Es'))               
        fsu = float(request.form.get('fsu'))                  
        esh = float(request.form.get('esh'))                
        esu = float(request.form.get('esu'))                   

        Ey = float(request.form.get('Ey'))                     
        C1 = float(request.form.get('C1'))                      

        csid = request.form.get('csid')    
        ssid = request.form.get('ssid')    

        ecser = float(request.form.get('ecser'))     
        esser = float(request.form.get('esser'))         
        ecdam = request.form.get('ecdam')      
        esdam = float(request.form.get('esdam'))         

        temp = float(request.form.get('temp'))              
        kLsp = float(request.form.get('kLsp'))             
                        
        theta = float(request.form.get('theta'))             #Ex
        thetaD = float(request.form.get('thetaD'))            #Ex       
        phiS = float(request.form.get('phiS'))           #Ex

        # Control parameters
        itermax = 1000          # max number of iterations (1000)
        ncl = 40                # of concrete layers (40)
        tolerance = 0.001       # x fpc x Ag (0.001)
        dels = 0.0001 
       
        MLR = MLR[MLR[:, 0].argsort()]

        # ??? addpath('C:\CUMBIA\models')                

        if Ec == 0:
            Ec = 5000 * np.sqrt(fpc)

        if temp < 0:
            Ct = (1 - 0.0105 * temp) * 0.56 * np.sqrt(fpc)   
        else:
            Ct = 0.56 * np.sqrt(fpc)

        eccr = Ct / Ec            
 
        if np.sum(wi) == 0 and MLR.shape[0] > 1:
            Pbars = MLR[0, 1] + MLR[-1, 1] + 2 * (MLR.shape[0] - 2) 
    
            wi = np.concatenate([
                np.ones(MLR[0, 1] - 1) * ((B - 2 * clb - MLR[0, 1] * MLR[0, 2]) / (MLR[0, 1] - 1)),
                np.ones(MLR[-1, 1] - 1) * ((B - 2 * clb - MLR[-1, 1] * MLR[-1, 2]) / (MLR[-1, 1] - 1)),
                np.diff(MLR[:, 0]) - np.mean(MLR[:, 2]),
                np.diff(MLR[:, 0]) - np.mean(MLR[:, 2])
            ])
    
        if sum(wi) == 0 and MLR.shape[0] == 1:
            wi = [
                (H - 2 * clb - 2 * MLR[0, 2]) * np.array([1, 1]),
                (B - 2 * clb - 2 * MLR[0, 2]) * np.array([1, 1])
            ]
            wi = np.concatenate(wi)
        #############return f"wi={wi}  -  MLR={MLR}   -  Ec={Ec} -  Ct={Ct} -  eccr={eccr}"
        
        Ast = np.sum(MLR[:, 1] * 0.25 * np.pi * MLR[:, 2] ** 2)
        
        Hcore = H - 2 * clb + Dh        # Core heigth
        Bcore = B - 2 * clb + Dh        # core width
        dcore = clb - Dh * 0.5          # distance to the core

        P = P * 1000                    # axial load in Newtons

        tcl = H / ncl                       # Thickness of concrete layers
        yl = tcl * np.arange(1, ncl + 1)    # border distance conc. layer

        esser = -esser
        esdam = -esdam

        # Load material models
        if unconfined.lower() == 'mu':
            ecun,fcun = manderun(Ec,Ast,Dh,clb,s,fpc,fyh,eco,esm,espall,'rectangular',0,H,B,ncx,ncy,wi,dels)
        elif unconfined.lower() == 'mc':
            ecun,fcun = manderconf(Ec,Ast,Dh,clb,s,fpc,fyh,eco,esm,espall,'rectangular',0,H,B,ncx,ncy,wi,dels,'hoops')
        elif unconfined.lower() == 'mclw':
            ecun,fcun = manderconflw(Ec,Ast,Dh,clb,s,fpc,fyh,eco,esm,espall,'rectangular',D,0,0,0,0,0,dels,typ)
        else:
            AUX = np.loadtxt(f"{unconfined}.txt")   # read the material model data file
            ecun = AUX[:, 0]
            fcun = AUX[:, 1]

      
        if confined.lower() == 'mu':
            ec, fc = manderun(Ec,Ast,Dh,clb,s,fpc,fyh,eco,esm,espall,'rectangular',0,H,B,ncx,ncy,wi,dels)
        elif confined.lower() == 'mc':
            ec, fc = manderconf(Ec,Ast,Dh,clb,s,fpc,fyh,eco,esm,espall,'rectangular',0,H,B,ncx,ncy,wi,dels,'hoops')
        elif confined.lower() == 'mclw':
            ec, fc = manderconflw(Ec,Ast,Dh,clb,s,fpc,fyh,eco,esm,espall,'rectangular',0,H,B,ncx,ncy,wi,dels,'hoops')
        else:
            AUX = np.loadtxt(f"{confined}.txt")   # read the material model data file
            ec = AUX[:, 0]
            fc = AUX[:, 1] 


        if rebar.lower() == 'ks':
            es, fs = steelking(Es,fy,fsu,esh,esu,dels)
        elif rebar.lower() == 'ra':
            es, fs = Raynor(Es,fy,fsu,esh,esu,dels,C1,Ey);
        else:
            AUX = np.loadtxt(f"{rebar}.txt")   # read the material model data file
            es = AUX[:, 0]
            fs = AUX[:, 1]

        # Ultimate strains
        ecu = ec[-1]                    # maximum strain confined concrete
        ecumander = ecu / 1.5           # ultimate strain predicted by the original mander model

        if ecdam.lower() == 'twth':
            ecdam = ecumander

        # Extend strain and stress vectors
        ec = np.concatenate(([-1e10], ec, [ec[-1] + dels, 1e10]))               # ector with strains of confined concrete
        fc = np.concatenate(([0], fc, [0, 0]))                                  # vector with stresses of confined concrete
        #return f"ec={[f'{x:.6f}' for x in ec]}" 
        ecun = np.append(np.insert(ecun, 0, -1e10), [ecun[-1] + dels, 1e10])    # vector with strains of unconfined concrete
        fcun = np.concatenate(([0], fcun, [0, 0]))                              # vector with stresses of unconfined concrete

        esu = es[-1]                                                            # maximum strain steel
        es = np.concatenate((es, [es[-1] + dels, 1e10]))                        # vector with strains of the steel
        fs = np.concatenate((fs, [0, 0]))                                       # vector with stresses of the steel    

        esaux = es[::-1] 
        fsaux = fs[::-1]
        es = np.concatenate((-esaux, es[1:]))                                   # vector with strains of the steel
        fs = np.concatenate((-fsaux, fs[1:]))  
        #return f"ec={[f'{x:.6f}' for x in ec]}  fc={fc}   ###  ecun={ecun} ###  fcun={fcun} ###  esaux={esaux} ###  fsaux={fsaux}"
        
        fig1 = stress_strain_relations_Confined(ec, fc, ecun, fcun)
        fig2 = stress_strain_relations_Reinforcing_Steel(es, fs)

        conclay = compute_concrete_layers(yl, dcore, H, Hcore, B, Bcore)
        
        distld, Asbs, diam = compute_rebars(MLR)

        conclay = CORRECTED_AREAS(conclay, Asbs, distld)

        def_, np_ = Define_vector(ecu, P, ecun, fcun, ec, fc, conclay, Ast, es, fs)
        
        np.savetxt("def.txt", def_, delimiter=",", fmt="%.6f")
        #return f"tolerance={tolerance} _______ H={H} _______ B={B} _______ fpc={fpc} _______ conclay={conclay} _______ distld={distld} _______ ecun={ecun} _______ fcun={fcun} _______ ec={ec} _______ fc={fc}"
        
        message, curv, mom, ejen, DF, vniter, coverstrain, corestrain, steelstrain, cores = CURVATURE_RELATION_ITERATIVE_PROCESS_TO_FIND_THE_MOMENT(tolerance, H, B, fpc, np_, def_, conclay, distld, ecun, fcun, ec, fc, es, fs, Asbs, P, itermax, dcore, confined, unconfined, ecu, esu)

        Agross, AsLong, LongSteelRatio, TransvSteelRatioX, TransvSteelRatioY, TransvSteelRatioAverage, AxialRatio, Mn, cr, cMn, fycurv, fyM, eqcurv, curvbilin, mombilin, SectionCurvatureDuctility, esaux = Gross_area_and_steel_ratios(H, B, Ast, ncx, ncy, Dh, s, Hcore, Bcore, P, fpc, ecser, coverstrain, mom, steelstrain, esser, ejen, Ec, fy, Es, curv)
 
        fig3 = Moment_Curvature_Relation(curvbilin, mombilin, curv, mom)

        Lp, LBE, bucritMK, failCuDuMK, failss, Lsp, CuDu, fig4 = calculate_plastic_hinge(MLR, steelstrain, Es, fy, kLsp, L, fsu, bending, s, diam, curv, eqcurv, SectionCurvatureDuctility)

        # Berry - Eberhard Buckling model
        #return f"curv={[f'{x:.6f}' for x in curv]}" #  fc={fc}   ###  ecun={ecun} ###  fcun={fcun} ###  esaux={esaux} ###  fsaux={fsaux}"

        bucritBE = 0
        C0 = 0.019          # model constants
        C1 = 1.650
        C2 = 1.797
        C3 = 0.012
        C4 = 0.072

        roeff = (2 * TransvSteelRatioAverage) * fyh / fpc           # effective confinement ratio
        rotb = C0 * (1 + C1 * roeff) * (1 + C2 * P / (Agross * fpc)) ** -1 * (1 + C3 * LBE / H + C4 * diam[0] * fy / H) # plastic rotation at the onset of bar buckling
        
        plrot = (curv - fycurv) * Lp / 1000
        
        failCuDuBE, bucritBE, fig5 = Berry_Eberhard_Buckling_Model(CuDu, plrot, rotb, bucritBE)
        #return f"bending={bending}  ____ curv={curv}  ____ coverstrain={coverstrain}  ____ eccr={eccr}  ____ fycurv={fycurv}  ____ L={L}  ____ Lsp={Lsp}  ____ fyM={fyM}"
        displf, Force = calculate_displacement_and_force(bending, curv, coverstrain, eccr, fycurv, L, Lsp, Lp, mom, fyM)

        #return f"displf={displf}  ____ Force={Force}"
        Vc1, kscr, kseff, forcebilin, displsh, G = shear_deflection(Ec, B, H, L, Mn, eqcurv, LongSteelRatio, bending, fpc, dcore, TransvSteelRatioY, Es, mombilin, curv, Force, mom, displf)
        
        # Total displacement
        displ = np.array(displsh) + np.array(displf)
        np.savetxt("displ.txt", displ, delimiter=",", fmt="%.6f")
        np.savetxt("displf.txt", displf, delimiter=",", fmt="%.6f")
        np.savetxt("displsh.txt", displsh, delimiter=",", fmt="%.6f")
        np.savetxt("Force.txt", Force, delimiter=",", fmt="%.6f")
        
        #return f"{len(displsh)} displsh={displsh}  ____ displ={displ}  ____{len(displf)}  displf={displf}"
        # Bilinear approximation
        dy1 = np.interp(fycurv, curv, displ)
        dy = (Mn / fyM) * dy1
        du = displ[-1]
        displbilin = [0, dy, du]
        Dduct = displ / dy
        DisplDuct = max(Dduct)

        dy1f = np.interp(fycurv, curv, displf)
        dyf = (Mn / fyM) * dy1f
        
        V, Vd, criteria, faildispl, failforce, failduct, failcurv, failCuDu, failmom = shear_strength(ncy, Dh, fyh, H, clb, cMn, s, theta, thetaD, LongSteelRatio, displ, dyf, L, P, bending, ductilitymode, fpc, Agross, phiS, Force, Dduct, mom, curv, CuDu, dy)
        #return f"faildispl={faildispl}    ##########  failforce={failforce}" 
        Ieq = (Mn / (eqcurv * Ec)) / 1000
        Bi = 1 / (((mombilin[1]) / (curvbilin[1])) / ((mombilin[2] - mombilin[1]) / (curvbilin[2] - curvbilin[1])))

        outputlimit, displdam, displser,ifff = Limit_States(coverstrain, steelstrain, displ, Dduct, curv, CuDu, mom, Force, ecser, esser, ecdam, esdam)
        #return f"#### displ={[f'{x:.6f}' for x in displ]} - ###### CuDu={CuDu} - ###### failCuDuMK={failCuDuMK} - ###### Force={[f'{x:.6f}' for x in Force]}"
        failCuDuMK, failCuDuBE, buckldispl, bucklforce, fig6 = Force_Displacement_Relation(displbilin, forcebilin, displ, Force, V, Vd, criteria, faildispl, failforce, bucritMK, failCuDuMK, CuDu, bucritBE, failCuDuBE)
        buckldispl = np.interp(failCuDuMK, CuDu, displ)
        bucklforce = np.interp(failCuDuMK, CuDu, Force)
        #return f"buckldispl={buckldispl}    ##########  bucklforce={bucklforce}"   
        buckldispl, bucklforce, buckldisplBE, bucklforceBE, fig7 = Potential_Deformation_Limit_States(displ, Force, displbilin, forcebilin, displdam, displser, V, Vd, criteria, faildispl, failforce, bucritMK, failCuDuMK, CuDu, bucritBE, failCuDuBE)
        #return fig1+fig2+fig3+fig4+fig5+fig6+fig7
        
        output = np.vstack([coverstrain, corestrain, ejen, steelstrain, mom, curv, Force, displsh, displf, displ, V, Vd]).T
        outputbilin = np.vstack([curvbilin, mombilin, displbilin, forcebilin])
        Acore = Hcore * Bcore
        PCid = np.interp(csid, ec, fc) * (Acore - AsLong) + np.interp(csid, ecun, fcun) * (Agross - Acore) + AsLong * np.interp(csid, es, fs)
        PTid = AsLong * np.interp(ssid, es, fs)
        
        html_1 = html_01(Dh=12.5, s=200, ncx=4, ncy=6, P=50000, fpc=30, fy=420, fs=450, fyh=250, confined='mclw', B=500, H=700, clb=40, MLR=[[100, 4, 16], [200, 6, 20], [300, 8, 25]])
        html_2 = html_02(Dh=12.5, s=200, ncx=4, ncy=6, P=50000, fpc=30, fy=420, fs=450, fyh=250)
        html_3 = html_03(bending, ductilitymode, LongSteelRatio, TransvSteelRatioAverage, AxialRatio, output)
        
        html_4 = html_04(outputbilin, message, fyM, fycurv, Mn, eqcurv, SectionCurvatureDuctility, DisplDuct) 
        
        html_5 = html_05(criteria, faildispl, failduct, failforce, failcurv, failCuDu, failmom)
        
        results = []
        if bucritMK == 1:
            bucklDd = interp1d(CuDu, Dduct, fill_value="extrapolate")(failCuDuMK)
            bucklcurv = interp1d(CuDu, curv, fill_value="extrapolate")(failCuDuMK)
            bucklmom = interp1d(CuDu, mom, fill_value="extrapolate")(failCuDuMK)
            results.append({
                'model': 'Moyer - Kowalsky',
                'failCuDu': failCuDuMK,
                'bucklcurv': bucklcurv,
                'bucklDd': bucklDd,
                'buckldispl': buckldispl,
                'bucklforce': bucklforce,
                'bucklmom': bucklmom
            })
    
        if bucritBE == 1:
            bucklDdBE = interp1d(CuDu, Dduct, fill_value="extrapolate")(failCuDuBE)
            bucklcurvBE = interp1d(CuDu, curv, fill_value="extrapolate")(failCuDuBE)
            bucklmomBE = interp1d(CuDu, mom, fill_value="extrapolate")(failCuDuBE)
            results.append({
                'model': 'Berry - Eberhard',
                'failCuDu': failCuDuBE,
                'bucklcurv': bucklcurvBE,
                'bucklDd': bucklDdBE,
                'buckldispl': buckldisplBE,
                'bucklforce': bucklforceBE,
                'bucklmom': bucklmomBE
            })  
   
        html_6 = render_template('display6.html', results=results)

        html_7 = html_07(outputlimit, ecser, esser, ecdam, esdam, confined, ecumander, Ec, G, Agross, Ieq, Bi, Lp, PTid, PCid, Mn)
        
        #buckldispl, bucklforce, buckldisplBE, bucklforceBE, fig8 = Potential_Deformation_Limit_States(displ, Force, displbilin, forcebilin, displdam, displser, V, Vd, criteria, faildispl, failforce, bucritMK, failCuDuMK, CuDu, bucritBE, failCuDuBE)
        outputi, esi, eci, i, csid, ssid, outputi, PTid, PCid, PB, MB, PB13, MB13, PB23, MB23, PPn, MnL, PPL, Mni = calculate_moment_capacity(PTid, fpc, Agross, PCid, ecun, ecu, esu, fcun, conclay, distld, ec, es, fc, fs, Ast, H, B, tolerance, itermax, csid, ssid, confined, unconfined, cores, esaux)

        fig9 = Interaction_Diagram(Mni, PPn, MnL, PPL)

        html_8 =  html_08(csid, ssid, outputi, PTid, PCid, PB, MB, PB13, MB13, PB23, MB23) 
        fig10 = Concrete_Strain(PPn, eci, i)
        fig11 =  Steel_Strain(PPn, esi, i)
        custom_html = render_template('mainRep.html', fig1=fig1, fig2=fig2, fig3=fig3, fig4=fig4, fig5=fig5, fig6=fig6, fig7=fig7 , fig9=fig9, fig10=fig10, fig11=fig11, html1=html_1, html3=html_3, html4=html_4, html5=html_5, html6=html_6, html7=html_7, html8=html_8)
        return custom_html #+html_2+html_3+html_4+html_5+html_6+html_7+html_8
        
if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0', port=5000)