using FeMM.Grasshopper.Helpers;
using Grasshopper.Kernel;
using Grasshopper.Kernel.Data;
using Grasshopper.Kernel.Types;
using St7API;
using System;
using System.Collections.Generic;
using System.Text;

namespace FeMM.Grasshopper.Components.ST2R
{
    public class St7ReadBeamVonMisesComponent : GH_Component
    {
        private bool _run = false;

        public St7ReadBeamVonMisesComponent()
            : base(
                "Read Beam Von Mises Stress",
                "ReadBeamVM",
                "Reads Von Mises stress from the result file",
                CategoryNameConstants.CATEGORY_F2R,
                CategoryNameConstants.SUBCATEGORY_ST2R_BAKE)
        { }

        public override void CreateAttributes()
        {
            var buttonAttributes = new ComponentAttributes.ComponentOneButtonAttributes(this, "Read");
            buttonAttributes.ButtonPressed += () =>
            {
                _run = true;
                ExpireSolution(true);
            };
            m_attributes = buttonAttributes;
        }

        protected override void RegisterInputParams(GH_InputParamManager p)
        {
            p.AddIntegerParameter("uID", "ID", "uID of the opened Straus7 model", GH_ParamAccess.item);
            p.AddTextParameter("Result File", "Res", "Path to .NLA / .NLF / .RST result file", GH_ParamAccess.item);
            p.AddIntegerParameter("Beam Number", "BeamNum", "Beam number(s)", GH_ParamAccess.list);
            p.AddIntegerParameter("Min Stations", "Min", "Minimum number of stations", GH_ParamAccess.item, 5);
        }

        protected override void RegisterOutputParams(GH_OutputParamManager p)
        {
            p.AddTextParameter("Case Names", "Names", "Result case / envelope names", GH_ParamAccess.tree);
            p.AddNumberParameter("Positions", "P", "Station positions", GH_ParamAccess.tree);
            p.AddNumberParameter("Von Mises Stress", "σVM", "von Mises stress", GH_ParamAccess.tree);
            p.AddTextParameter("Log", "Log", "Debug log messages", GH_ParamAccess.list);
        }

        protected override void SolveInstance(IGH_DataAccess DA)
        {
            int uID = 0;
            string resultFile = "";
            List<int> beamNums = [];
            int minStations = 5;

            if (!DA.GetData(0, ref uID)) return;
            if (!DA.GetData(1, ref resultFile)) return;
            if (!DA.GetDataList(2, beamNums)) return;
            if (!DA.GetData(3, ref minStations)) return;

            List<string> log = [];

            if (!_run)
            {
                DA.SetDataList(3, log);
                return;
            }

            int numPrimary = 0;
            int numSecondary = 0;

            int err = St7.St7OpenResultFile(
                uID,
                resultFile,
                null,
                St7.kUseExistingCombinations,
                ref numPrimary,
                ref numSecondary);

            if (err != 0)
            {
                log.Add($"Error opening result file: {err}");
                DA.SetDataList(3, log);
                _run = false;
                return;
            }

            int numLimitEnv = 0, numComboEnv = 0, numFactorEnv = 0;
            St7.St7GenerateEnvelopes(uID, ref numLimitEnv, ref numComboEnv, ref numFactorEnv);

            GH_Structure<GH_String> treeNames = new();
            GH_Structure<GH_Number> treePos = new();
            GH_Structure<GH_Number> treeVM = new();

            int beamIndex = 0;

            foreach (int beamNum in beamNums)
            {
                int caseBranchIndex = 0;

                void ReadCase(int caseNum, string caseName)
                {
                    int maxStations = 200;
                    int maxCols = 9; // NumColumns for rtBeamAllStress
                    double[] pos = new double[maxStations];
                    double[] res = new double[maxStations * maxCols];

                    int nStations = 0;
                    int nCols = 0;

                    int errBeam = St7.St7GetBeamResultArray(
                        uID,
                        St7.rtBeamAllStress,
                        1,
                        beamNum,
                        minStations,
                        caseNum,
                        ref nStations,
                        ref nCols,
                        pos,
                        res);

                    if (errBeam != 0)
                    {
                        log.Add($"Error reading beam {beamNum} von Mises for {caseName}: {errBeam}");
                        return;
                    }

                    GH_Path path = new(beamIndex, caseBranchIndex);

                    for (int i = 0; i < nStations; i++)
                    {
                        int baseIndex = i * nCols;
                        treeNames.Append(new GH_String(caseName), path);
                        treePos.Append(new GH_Number(pos[i]), path);
                        treeVM.Append(new GH_Number(res[baseIndex + St7.ipVonMisesStress]), path);
                    }

                    caseBranchIndex++;
                }

                for (int i = 1; i <= numPrimary; i++)
                {
                    var name = new StringBuilder(256);
                    if (St7.St7GetResultCaseName(uID, i, name, name.Capacity) == 0)
                        ReadCase(i, name.ToString().TrimEnd('\0'));
                }

                for (int i = 1; i <= numSecondary; i++)
                {
                    var name = new StringBuilder(256);
                    if (St7.St7GetLSACombinationName(uID, i, name, name.Capacity) == 0)
                        ReadCase(i + numPrimary, name.ToString().TrimEnd('\0'));
                }

                int baseEnv = numPrimary + numSecondary;
                for (int i = 1; i <= numLimitEnv + numComboEnv + numFactorEnv; i++)
                {
                    var name = new StringBuilder(256);
                    if (St7.St7GetResultCaseName(uID, baseEnv + i, name, name.Capacity) == 0)
                        ReadCase(baseEnv + i, name.ToString().TrimEnd('\0'));
                }

                beamIndex++;
            }

            DA.SetDataTree(0, treeNames);
            DA.SetDataTree(1, treePos);
            DA.SetDataTree(2, treeVM);
            DA.SetDataList(3, log);

            _run = false;
        }

        protected override System.Drawing.Bitmap Icon => Properties.Resources.St7ReadBeamVonMisesIcon;

        public override Guid ComponentGuid =>
            new("e3c2f9d7-8d4b-4d6f-a8c4-2d7b5e9f1a7c");
    }
}
303 files24 directories