import streamlit as st
import pandas as pd
from RFEM.initModel import Model, Calculate_all
from RFEM.BasicObjects.material import Material
from RFEM.BasicObjects.section import Section
from RFEM.BasicObjects.node import Node
from RFEM.BasicObjects.member import Member
from RFEM.TypesForNodes.nodalSupport import NodalSupport
from RFEM.LoadCasesAndCombinations.staticAnalysisSettings import StaticAnalysisSettings
from RFEM.LoadCasesAndCombinations.loadCase import LoadCase
from RFEM.Loads.memberLoad import MemberLoad
from RFEM.Results.resultTables import ResultTables, GetMaxValue, GetMinValue
from RFEM.dataTypes import inf
from RFEM.enums import CaseObjectType
import plotly.graph_objects as go


st.set_page_config(layout='wide')
st.markdown("# RFEM Web Integration")

inputCol, resultCol = st.columns([1, 2])

with inputCol:
    with st.form('inputForm'):
        firstSpanLength = st.number_input("First Span Length (m)", value = 3.0)
        secondSpanLength = st.number_input("Second Span Length (m)", value = 4.0)
        material = st.text_input("Material", value='S235')
        section = st.text_input("Section", value='IPE 300')
        spanLoad = st.number_input("Distributed Load (kNm)", value=2.0)
        calculateButton = st.form_submit_button("Calculate")

xcoords = [0, firstSpanLength, firstSpanLength+secondSpanLength]
ycoords = [0, 0, 0]

defaultFig = go.Figure()
defaultFig.add_trace(go.Scatter(
    x = xcoords,
    y = ycoords,
    line=dict(width = 3)
))

defaultFig.add_trace(go.Scatter(
    x = [firstSpanLength/2, firstSpanLength + (secondSpanLength/2)],
    y = [0,0],
    mode="text",
    text=[section, section],
    textposition="bottom center",
    textfont=dict(
        family="sans serif",
        size=16,
        color="DarkSlateGrey"),
))

defaultFig.add_trace(go.Scatter(
    x = [0, firstSpanLength, firstSpanLength+secondSpanLength],
    y = [0,0,0],
    mode="markers",
    marker = dict(symbol = 'arrow', size=15, color = "lightskyblue", line=dict(width=2, color="DarkSlateGrey"))
))

defaultFig.update_yaxes(
    range = [-0.2, 0.4],
    showgrid = False,
    showticklabels = False
)

defaultFig.update_layout(showlegend=False, width = 800, height=300)
spanLoad = round(spanLoad, 2)
defaultFig.add_trace(go.Scatter(
    x = [(firstSpanLength+secondSpanLength)/2],
    y = [0.25],
    mode="text",
    text=[str(spanLoad) + ' kN/m'],
    textposition="top center",
    textfont=dict(
        family="sans serif",
        size=16,
        color="DarkSlateGrey"),
))

import numpy as np
arrowPoints = np.arange(0, firstSpanLength+secondSpanLength + 0.5, 0.5)

for i in arrowPoints:
    defaultFig.add_annotation(
            x=i,
            y=0.05,
            xref="x",
            yref="y",
            ax=0,
            ay=-50,
            showarrow=True)

results = pd.DataFrame(columns=['Members', 'Maximum Displacement (mm)', 'Maximum Bending Moment (kNm)'])
results['Members'] = ['First Span', 'Second Span']
results['Maximum Displacement (mm)'] = [0, 0]
results['Maximum Bending Moment (kNm)'] = [0, 0]

if calculateButton:

    Model(True, "webAppBeam.rf6")
    Model.clientModel.service.delete_all()
    Model.clientModel.service.begin_modification()
    
    Material(1, material)

    Section(1, section)

    Node(1, 0,0,0)
    Node(2, firstSpanLength, 0,0)
    Node(3, firstSpanLength+secondSpanLength,0,0)

    Member(1, 1, 2, 0, 1, 1)
    Member(2, 2, 3, 0, 1, 1)

    NodalSupport(1, '1 2 3', [inf, inf ,inf, inf, 0, inf])

    StaticAnalysisSettings(1, "Linear")

    LoadCase(1, "Load")

    MemberLoad(1, 1, '1', magnitude=spanLoad*1000)
    MemberLoad(2, 1, '2', magnitude=spanLoad*1000)

    Calculate_all()

    dispTableFirst = ResultTables.MembersGlobalDeformations(CaseObjectType.E_OBJECT_TYPE_LOAD_CASE, 1, 1)
    firstMaxDisp = GetMaxValue(dispTableFirst, 'displacement_absolute') * 1000

    secondTableFirst = ResultTables.MembersGlobalDeformations(CaseObjectType.E_OBJECT_TYPE_LOAD_CASE, 1, 2)
    secondMaxDisp = GetMaxValue(secondTableFirst, 'displacement_absolute') * 1000

    momentTableFirst = ResultTables.MembersInternalForces(CaseObjectType.E_OBJECT_TYPE_LOAD_CASE, 1, 1)
    maxMomentFirst = GetMinValue(momentTableFirst, 'internal_force_my')

    momentTableSecond = ResultTables.MembersInternalForces(CaseObjectType.E_OBJECT_TYPE_LOAD_CASE, 1, 2)
    maxMomentSecond = GetMaxValue(momentTableSecond, 'internal_force_my')

    results['Maximum Displacement (mm)'] = [firstMaxDisp, secondMaxDisp]
    results['Maximum Bending Moment (kNm)'] = [maxMomentFirst/1000, maxMomentSecond/1000]

    Model.clientModel.service.finish_modification()
    Model.clientModel.service.close_connection()

with resultCol:
    st.markdown("## Result Table")
    st.plotly_chart(defaultFig)
    st.table(results)