# Fairyfly: A Plugin for Environmental Analysis (GPL)
# This file is part of Fairyfly.
#
# Copyright (c) 2025, Ladybug Tools.
# You should have received a copy of the GNU Affero General Public License
# along with Fairyfly; If not, see <http://www.gnu.org/licenses/>.
# 
# @license AGPL-3.0-or-later <https://spdx.org/licenses/AGPL-3.0-or-later>

"""
Create Fairyfly Boundary.
-

    Args:
        _thmz: Path to a THMZ file that has been simulated in THERM. This can be the
            direct output of the "FF Model to THMZ" component as long as
            run_ has been set to True.
        _data_type_: Optional text or an integer to set the type of result data to import from
            the THMZ file. Choose from the following options. (Default: Temperature)
                0 - Temperature (C or F)
                1 - Heat Flux (W/m2 or Btu/h-ft2)
        ip_: Set to True to have all data imported with IP Units (Farenheit and Btu/h-ft2)
            instead of the default SI units of Celsius and W/m2.
        legend_par_: Optional legend parameters from the "LB Legend Parameters"
            that will be used to customize the display of the results.

    Returns:
        report: Reports, errors, warnings, etc.
        shape_geo: A list of breps for the geometry of the Shapes contained within
            the THMZ file. The edges of these shapes can be used to overlay
            wireframe visualizations on top of the result mesh.
        points: The grid of points representing the nodes of the mesh generated by THERM.
        results: A list of numbers that aligns with the points. Each number indicates
            the temeprature (or heat flux) at each of the points.
        mesh: A colored mesh produced from the model's shapes representing the
            temperature or heat flow through the construction.
        legend: A legend showing the values that correspond to the colors of the mesh.
        title: A text object for the study title.
        vis_set: A VisualizationSet object for drawing a detailed version of the
            Therm results in the Rhino scene. This can be connected to
            the "LB Preview Visualization Set" component to display this
            version of the results in Rhino.
"""

ghenv.Component.Name = 'FF Read THERM Result'
ghenv.Component.NickName = 'ThermResult'
ghenv.Component.Message = '1.9.3'
ghenv.Component.Category = 'Fairyfly'
ghenv.Component.SubCategory = '1 :: THERM'
ghenv.Component.AdditionalHelpFromDocStrings = '2'

try:  # import the core fairyfly dependencies
    from fairyfly_therm.result import THMZResult
except ImportError as e:
    raise ImportError('\nFailed to import fairyfly:\n\t{}'.format(e))

try:  # import the core ladybug dependencies
    from ladybug.graphic import GraphicContainer
    from ladybug.legend import LegendParameters
    from ladybug.color import Colorset
    from ladybug.datatype.temperature import Temperature
    from ladybug.datatype.energyflux import EnergyFlux
except ImportError as e:
    raise ImportError('\nFailed to import ladybug:\n\t{}'.format(e))

try:
    from ladybug_display.visualization import VisualizationSet
    from ladybug_display.context import ContextGeometry
    from ladybug_display.geometry3d import DisplayLineSegment3D
except ImportError as e:
    raise ImportError('\nFailed to import ladybug:\n\t{}'.format(e))

try:  # import the ladybug_rhino dependencies
    from ladybug_rhino.config import conversion_to_meters
    from ladybug_rhino.fromgeometry import from_mesh3d, from_point3d, from_face3d
    from ladybug_rhino.fromobjects import legend_objects
    from ladybug_rhino.text import text_objects
    from ladybug_rhino.grasshopper import all_required_inputs, give_warning, \
        hide_output, show_output
except ImportError as e:
    raise ImportError('\nFailed to import ladybug_rhino:\n\t{}'.format(e))

DATA_TYPES = {
    'none': 'temperatures',
    'temperature': 'temperatures',
    '0': 'temperatures',
    'heat flux': 'heat_flux_magnitudes',
    '1': 'heat_flux_magnitudes'
}


if all_required_inputs(ghenv.Component):
    # create the THMZResult object and check to be sure that it has been simulated
    result_obj = THMZResult(_thmz)
    study_mesh = result_obj.mesh
    if study_mesh is None:
        msg = 'No mesh was found within the THMZ file.\nMake sure that the THMZ ' \
            'file has been successfully simulated in THERM.'
        print(msg)
        give_warning(ghenv.Component, msg)

    else:
        # scale the mesh to the current Rhino model units
        conversion = 0.001 / conversion_to_meters()
        study_mesh = study_mesh.scale(conversion)
        shape_geo = result_obj.shape_faces
        shape_geo = [f.scale(conversion) for f in shape_geo]

        # get the results from the THMZ file
        data_attr = DATA_TYPES[str(_data_type_).lower()]
        results = getattr(result_obj, data_attr)
        if results is None:
            msg = 'No steady state results were found within the THMZ file.\n' \
                'Make sure that the THMZ has been set up for steady state simulation ' \
                'and has been successfully simulated in THERM.'
            print(msg)
            give_warning(ghenv.Component, msg)
        else:
            # process the results into the correct units
            if data_attr == 'temperatures':
                units = 'F' if ip_ else 'C'
                study_name = 'Temperature [{}]'.format(units)
                if ip_:
                    results = Temperature().to_ip(results, 'C')[0]
            else:
                units = 'Btu/h-ft2' if ip_ else 'W/m2'
                study_name = 'Heat Flux [{}]'.format(units)
                if ip_:
                    results = EnergyFlux().to_ip(results, 'W/m2')[0]

            # # create the mesh and legend outputs
            l_par = legend_par_ if legend_par_ is not None else LegendParameters()
            if l_par.are_colors_default:
                l_par.colors = Colorset.therm()
            graphic = GraphicContainer(results, study_mesh.min, study_mesh.max, l_par)
            graphic.legend_parameters.title = units
            title = text_objects(
                study_name, graphic.lower_title_location,
                graphic.legend_parameters.text_height * 1.5,
                graphic.legend_parameters.font)

            # create the visual outputs
            study_mesh.colors = graphic.value_colors
            legend = legend_objects(graphic.legend)
            # create the VisualizationSet
            vis_set = VisualizationSet.from_single_analysis_geo(
                'Therm_Results', [study_mesh], results, graphic.legend_parameters)
            wireframe = []
            for face3d in shape_geo:
                for seg in face3d.boundary_segments:
                    wireframe.append(DisplayLineSegment3D(seg, line_width=2))
                if face3d.has_holes:
                    for hole in face3d.hole_segments:
                        for seg in hole:
                            wireframe.append(DisplayLineSegment3D(seg, line_width=2))
            con_outline = ContextGeometry('Wireframe', wireframe)
            vis_set.add_geometry(con_outline)

        # create the visual outputs
        shape_geo = [from_face3d(f) for f in shape_geo]
        points = [from_point3d(pt) for pt in study_mesh.vertices]
        mesh = from_mesh3d(study_mesh)

    # hide the points from the scene
    hide_output(ghenv.Component, 1)
    hide_output(ghenv.Component, 2)
