/*
 * Copyright 2023 Adobe. All rights reserved.
 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License. You may obtain a copy
 * of the License at http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under
 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
 * OF ANY KIND, either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
#pragma once

#define LAGRANGE_TARGET_OS(X) LAGRANGE_TARGET_OS_PRIVATE_DEFINITION_##X()

#if defined(_WIN32) || defined(_WIN64)
    #define LAGRANGE_TARGET_OS_PRIVATE_DEFINITION_WINDOWS() 1
    #define LAGRANGE_TARGET_OS_PRIVATE_DEFINITION_LINUX() 0
    #define LAGRANGE_TARGET_OS_PRIVATE_DEFINITION_APPLE() 0
    #define LAGRANGE_TARGET_OS_PRIVATE_DEFINITION_WASM() 0
#elif defined(__APPLE__)
    #define LAGRANGE_TARGET_OS_PRIVATE_DEFINITION_WINDOWS() 0
    #define LAGRANGE_TARGET_OS_PRIVATE_DEFINITION_APPLE() 1
    #define LAGRANGE_TARGET_OS_PRIVATE_DEFINITION_LINUX() 0
    #define LAGRANGE_TARGET_OS_PRIVATE_DEFINITION_WASM() 0
#elif defined(__linux__)
    #define LAGRANGE_TARGET_OS_PRIVATE_DEFINITION_WINDOWS() 0
    #define LAGRANGE_TARGET_OS_PRIVATE_DEFINITION_APPLE() 0
    #define LAGRANGE_TARGET_OS_PRIVATE_DEFINITION_LINUX() 1
    #define LAGRANGE_TARGET_OS_PRIVATE_DEFINITION_WASM() 0
#elif defined(__wasm__)
    #define LAGRANGE_TARGET_OS_PRIVATE_DEFINITION_WINDOWS() 0
    #define LAGRANGE_TARGET_OS_PRIVATE_DEFINITION_APPLE() 0
    #define LAGRANGE_TARGET_OS_PRIVATE_DEFINITION_LINUX() 0
    #define LAGRANGE_TARGET_OS_PRIVATE_DEFINITION_WASM() 1
#else
    #error "Platform not supported"
#endif

#define LAGRANGE_TARGET_COMPILER(X) LAGRANGE_TARGET_COMPILER_PRIVATE_DEFINITION_##X()

#if defined(__EMSCRIPTEN__)
    #define LAGRANGE_TARGET_COMPILER_PRIVATE_DEFINITION_MSVC() 0
    #define LAGRANGE_TARGET_COMPILER_PRIVATE_DEFINITION_CYGWIN() 0
    #define LAGRANGE_TARGET_COMPILER_PRIVATE_DEFINITION_CLANG() 0
    #define LAGRANGE_TARGET_COMPILER_PRIVATE_DEFINITION_GCC() 0
    #define LAGRANGE_TARGET_COMPILER_PRIVATE_DEFINITION_EMSCRIPTEN() 1
#elif defined(_MSC_VER)
    #define LAGRANGE_TARGET_COMPILER_PRIVATE_DEFINITION_MSVC() 1
    #define LAGRANGE_TARGET_COMPILER_PRIVATE_DEFINITION_CYGWIN() 0
    #define LAGRANGE_TARGET_COMPILER_PRIVATE_DEFINITION_CLANG() 0
    #define LAGRANGE_TARGET_COMPILER_PRIVATE_DEFINITION_GCC() 0
    #define LAGRANGE_TARGET_COMPILER_PRIVATE_DEFINITION_EMSCRIPTEN() 0
#elif defined(__CYGWIN__)
    #define LAGRANGE_TARGET_COMPILER_PRIVATE_DEFINITION_MSVC() 0
    #define LAGRANGE_TARGET_COMPILER_PRIVATE_DEFINITION_CYGWIN() 1
    #define LAGRANGE_TARGET_COMPILER_PRIVATE_DEFINITION_CLANG() 0
    #define LAGRANGE_TARGET_COMPILER_PRIVATE_DEFINITION_GCC() 0
    #define LAGRANGE_TARGET_COMPILER_PRIVATE_DEFINITION_EMSCRIPTEN() 0
#elif defined(__clang__)
    #define LAGRANGE_TARGET_COMPILER_PRIVATE_DEFINITION_MSVC() 0
    #define LAGRANGE_TARGET_COMPILER_PRIVATE_DEFINITION_CYGWIN() 0
    #define LAGRANGE_TARGET_COMPILER_PRIVATE_DEFINITION_CLANG() 1
    #define LAGRANGE_TARGET_COMPILER_PRIVATE_DEFINITION_GCC() 0
    #define LAGRANGE_TARGET_COMPILER_PRIVATE_DEFINITION_EMSCRIPTEN() 0
#elif defined(__GNUC__)
    #define LAGRANGE_TARGET_COMPILER_PRIVATE_DEFINITION_MSVC() 0
    #define LAGRANGE_TARGET_COMPILER_PRIVATE_DEFINITION_CYGWIN() 0
    #define LAGRANGE_TARGET_COMPILER_PRIVATE_DEFINITION_CLANG() 0
    #define LAGRANGE_TARGET_COMPILER_PRIVATE_DEFINITION_GCC() 1
    #define LAGRANGE_TARGET_COMPILER_PRIVATE_DEFINITION_EMSCRIPTEN() 0
#else
    #error "Compiler not supported"
#endif

#define LAGRANGE_TARGET_PLATFORM(X) LAGRANGE_TARGET_PLATFORM_PRIVATE_DEFINITION_##X()

#if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || \
    defined(_M_X64) || defined(_M_AMD64)
    #define LAGRANGE_TARGET_PLATFORM_PRIVATE_DEFINITION_x86_64() 1
    #define LAGRANGE_TARGET_PLATFORM_PRIVATE_DEFINITION_arm64() 0
#elif defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC)
    #define LAGRANGE_TARGET_PLATFORM_PRIVATE_DEFINITION_x86_64() 0
    #define LAGRANGE_TARGET_PLATFORM_PRIVATE_DEFINITION_arm64() 1
#else
    #define LAGRANGE_TARGET_PLATFORM_PRIVATE_DEFINITION_x86_64() 0
    #define LAGRANGE_TARGET_PLATFORM_PRIVATE_DEFINITION_arm64() 0
#endif

#if defined(__wasm32__)
    #define LAGRANGE_TARGET_PLATFORM_PRIVATE_DEFINITION_wasm32() 1
    #define LAGRANGE_TARGET_PLATFORM_PRIVATE_DEFINITION_wasm64() 0
#elif defined(__wasm64__)
    #define LAGRANGE_TARGET_PLATFORM_PRIVATE_DEFINITION_wasm32() 0
    #define LAGRANGE_TARGET_PLATFORM_PRIVATE_DEFINITION_wasm64() 1
#else
    #define LAGRANGE_TARGET_PLATFORM_PRIVATE_DEFINITION_wasm32() 0
    #define LAGRANGE_TARGET_PLATFORM_PRIVATE_DEFINITION_wasm64() 0
#endif

#if !(                                                                     \
    LAGRANGE_TARGET_PLATFORM(x86_64) || LAGRANGE_TARGET_PLATFORM(arm64) || \
    LAGRANGE_TARGET_PLATFORM(wasm32) || LAGRANGE_TARGET_PLATFORM(wasm64))
    #error "Unexpected target platform setup"
#endif

#define LAGRANGE_TARGET_FEATURE(X) LAGRANGE_TARGET_FEATURE_PRIVATE_DEFINITION_##X()

#if __clang__ && !__INTEL_COMPILER
    #define LAGRANGE_ENABLE_RTTI __has_feature(cxx_rtti)
#elif defined(_CPPRTTI)
    #define LAGRANGE_ENABLE_RTTI 1
#else
    #define LAGRANGE_ENABLE_RTTI (__GXX_RTTI || __RTTI || __INTEL_RTTI__)
#endif

#if LAGRANGE_ENABLE_RTTI
    #define LAGRANGE_TARGET_FEATURE_PRIVATE_DEFINITION_RTTI() 1
#else
    #define LAGRANGE_TARGET_FEATURE_PRIVATE_DEFINITION_RTTI() 0
#endif
