# Parsing C++ structs.
#
# Author: Malte J. Ziebarth (malte.ziebarth@tum.de)
#
# Copyright (C) 2025-2026 Technische Universität München
#
# Licensed under the EUPL, Version 1.2 or – as soon they will be approved by
# the European Commission - subsequent versions of the EUPL (the "Licence");
# You may not use this work except in compliance with the Licence.
# You may obtain a copy of the Licence at:
#
# https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the Licence is distributed on an "AS IS" basis,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the Licence for the specific language governing permissions and
# limitations under the Licence.
#
# SPDX-FileCopyrightText: 2025-2026 Technical University of Munich
# SPDX-License-Identifier: EUPL-1.2
# SPDX-FileContributor: Malte J. Ziebarth <malte.ziebarth@tum.de>

from ..language.abstract import Struct
from ..language.fundamental import FBP_TO_FBP
from ..language.cpp import L1Type, CppArgumentType,\
    assert_l1_type

from .usertypes import UserTypeDict
from .variable import parse_variable


def parse_struct(
        s: str,
        user_types: UserTypeDict,
        fk_namespace: str
    ) -> Struct[L1Type]:
    """
    Parses the signature of a single struct.
    """
    # Split the structure body in curly braces:
    argsplit = s.split('{')
    if len(argsplit) != 2:
        raise RuntimeError(
            "Cannot split definition '" + s + "' into structure name "
            "and body. Need exactly one opening curly brace ('{'))."
        )
    argssplitsplit = argsplit[1].split('}')
    if len(argssplitsplit) != 2:
        raise RuntimeError(
            "Need exactly one closing curly brace ('}') in structure "
            " definition. Violating definition: '" + s + "'."
        )
    vars: list[str] = argssplitsplit[0].split(';')[:-1]

    # Structure name and 'struct' keyword:
    strct, name = argsplit[0].split()
    assert strct == 'struct'

    # Members:
    def to_l1_type(var: tuple[CppArgumentType, str]) -> tuple[L1Type, str]:
        return assert_l1_type(var[0].val), var[1]

    type_map: dict[str, L1Type] = {
        **user_types.types,
        **FBP_TO_FBP
    }

    parsed_members: list[tuple[L1Type, str]] = [
        to_l1_type(parse_variable(v, type_map, fk_namespace))
        for v in vars
    ]

    return Struct(name, parsed_members)