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 St7ReadBeamGlobalDispComponent : GH_Component
    {
        private bool _run = false;

        public St7ReadBeamGlobalDispComponent()
            : base(
                "Read Beam Global Displacement",
                "ReadBeamDisp",
                "Reads beam displacement results",
                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(
                "Dx", "Dx",
                "Global displacement X",
                GH_ParamAccess.tree);

            p.AddNumberParameter(
                "Dy", "Dy",
                "Global displacement Y",
                GH_ParamAccess.tree);

            p.AddNumberParameter(
                "Dz", "Dz",
                "Global displacement Z",
                GH_ParamAccess.tree);

            p.AddNumberParameter(
                "Rx", "Rx",
                "Global rotation X",
                GH_ParamAccess.tree);

            p.AddNumberParameter(
                "Ry", "Ry",
                "Global rotation Y",
                GH_ParamAccess.tree);

            p.AddNumberParameter(
                "Rz", "Rz",
                "Global rotation Z",
                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(8, 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(8, 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> treeDx = new();
            GH_Structure<GH_Number> treeDy = new();
            GH_Structure<GH_Number> treeDz = new();
            GH_Structure<GH_Number> treeRx = new();
            GH_Structure<GH_Number> treeRy = new();
            GH_Structure<GH_Number> treeRz = new();

            int beamIndex = 0;

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

                void ReadCase(int caseNum, string caseName)
                {
                    int maxStations = 200;
                    int maxCols = 6; // Dx Dy Dz Rx Ry Rz

                    double[] pos = new double[maxStations];
                    double[] res = new double[maxStations * maxCols];

                    int nStations = 0;
                    int nCols = 0;

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

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

                    GH_Path path = new(beamIndex, caseBranchIndex);

                    for (int i = 0; i < nStations; i++)
                    {
                        int b = i * nCols;

                        treeNames.Append(new GH_String(caseName), path);
                        treePos.Append(new GH_Number(pos[i]), path);

                        treeDx.Append(new GH_Number(res[b + 0]), path);
                        treeDy.Append(new GH_Number(res[b + 1]), path);
                        treeDz.Append(new GH_Number(res[b + 2]), path);
                        treeRx.Append(new GH_Number(res[b + 3]), path);
                        treeRy.Append(new GH_Number(res[b + 4]), path);
                        treeRz.Append(new GH_Number(res[b + 5]), path);
                    }

                    caseBranchIndex++;
                }

                // Primary cases
                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'));
                }

                // Secondary combinations
                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'));
                }

                // Envelopes
                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, treeDx);
            DA.SetDataTree(3, treeDy);
            DA.SetDataTree(4, treeDz);
            DA.SetDataTree(5, treeRx);
            DA.SetDataTree(6, treeRy);
            DA.SetDataTree(7, treeRz);
            DA.SetDataList(8, log);

            _run = false;
        }

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

        public override Guid ComponentGuid =>
            new("8f9a3e32-7e74-4a9a-9c1a-6a2c3a7c4d11");
    }
}
303 files24 directories