# String conversion.
#
# 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 .abstract import Pointer, Const, Struct
from .arrays import NDArray, QuantityArray
from .cpp import L2Type
from .python import CTypeType, P2Type
from .conversion import NUMPY_DTYPE_MAP


def ctypetype_string(t: CTypeType) -> str:
    if isinstance(t, Pointer):
        return "POINTER(" + ctypetype_string(t.val) + ")"
    elif isinstance(t, Const):
        return ctypetype_string(t.val)
    elif isinstance(t, Struct):
        return t.name
    return t


def type_string(t: P2Type) -> str:
    """
    Python type string for type hinting.
    """
    if isinstance(t, str):
        return t
    elif isinstance(t, Pointer):
        return '"_Pointer[' + type_string(t.val).replace('"','') + ']"'
    elif isinstance(t, Const):
        return type_string(t.val)
    elif isinstance(t, NDArray):
        return "\"NDArray[" \
            + NUMPY_DTYPE_MAP[t.ctypes_type()] \
            + "]\""
    elif isinstance(t, QuantityArray):
        return "QuantityArray"
    return t.name


def cpp_type_string(p: L2Type) -> str:
    """
    Converts an extended type to a C++ string.
    """
    if isinstance(p, Struct):
        return p.name
    elif isinstance(p, Pointer):
        if p.val == "char":
            return "char*"
        elif p.val == "void":
            return "void*"
        return cpp_type_string(p.val) + "*"
    elif isinstance(p, Const):
        return cpp_type_string(p.val) + " const"
    elif isinstance(p, QuantityArray):
        return (
            "funktionsklempner::QuantityArray"
            f"<{cpp_type_string(p.dtype)}>"
        )
    elif isinstance(p, NDArray):
        return (
            "funktionsklempner::ndarray::NDArray"
            f"<{cpp_type_string(p.dtype)}>"
        )
    elif p == "void":
        raise ValueError("Cannot have pure 'void' variable.")
    return p