# Copyright 2014-present PlatformIO <contact@platformio.org>
#
# Licensed 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 CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""
Arduino

Arduino Wiring-based Framework allows writing cross-platform software to
control devices attached to a wide range of Arduino boards to create all
kinds of creative coding, interactive objects, spaces or physical experiences.

http://arduino.cc/en/Reference/HomePage
"""

import os
import sys
import shutil
import hashlib
import threading
from contextlib import suppress
from os.path import join, exists, isabs, splitdrive, commonpath, relpath
from pathlib import Path
from typing import Union, List

from SCons.Script import DefaultEnvironment, SConscript
from platformio import fs
from platformio.package.manager.tool import ToolPackageManager

IS_WINDOWS = sys.platform.startswith("win")

# Constants for better performance
UNICORE_FLAGS = {
    "CORE32SOLO1",
    "CONFIG_FREERTOS_UNICORE=y"
}

# Thread-safe global flags to prevent message spam
_PATH_SHORTENING_LOCK = threading.Lock()
_PATH_SHORTENING_MESSAGES = {
    'shortening_applied': False,
    'no_framework_paths_warning': False,
    'long_path_warning_shown': False
}


def get_platform_default_threshold(mcu):
    """
    Platform-specific max performance default values for 
    INCLUDE_PATH_LENGTH_THRESHOLD
    These values push the limits for maximum performance and minimal path 
    shortening

    Args:
        mcu: MCU type (esp32, esp32s2, esp32s3, etc.)

    Returns:
        int: Platform-specific default threshold
    """
    # Max. performance values - pushing Windows command line limits
    # Windows CMD has ~32768 character limit, we use aggressive values close
    # to this
    platform_defaults = {
        "esp32": 32000,      # Standard ESP32
        "esp32s2": 32000,    # ESP32-S2
        "esp32s3": 32766,    # ESP32-S3
        "esp32c3": 30000,    # ESP32-C3
        "esp32c2": 32000,    # ESP32-C2
        "esp32c6": 31600,    # ESP32-C6
        "esp32h2": 32000,    # ESP32-H2
        "esp32p4": 32000,    # ESP32-P4
    }

    default_value = platform_defaults.get(mcu, 31600)

    return default_value


def validate_threshold(threshold, mcu):
    """
    Validates threshold value with max. performance limits
    Uses aggressive boundaries for maximum performance

    Args:
        threshold: Threshold value to validate
        mcu: MCU type for context-specific validation

    Returns:
        int: Validated threshold value
    """
    # Absolute limits - pushing boundaries
    min_threshold = 20000   # Minimum reasonable value for complex projects
    # Maximum aggressive value (beyond Windows CMD limit for testing)
    max_threshold = 32767

    # MCU-specific adjustments - all values are aggressive
    mcu_adjustments = {
        "esp32c2": {"min": 30000, "max": 32767},
        "esp32c3": {"min": 30000, "max": 32767},
        "esp32": {"min": 30000, "max": 32767},
        "esp32s2": {"min": 30000, "max": 32767},
        "esp32s3": {"min": 30000, "max": 32767},
        "esp32p4": {"min": 30000, "max": 32767},
        "esp32c6": {"min": 30000, "max": 32767},
        "esp32h2": {"min": 30000, "max": 32767},
    }

    # Apply MCU-specific max. limits
    if mcu in mcu_adjustments:
        min_threshold = max(min_threshold, mcu_adjustments[mcu]["min"])
        max_threshold = min(max_threshold, mcu_adjustments[mcu]["max"])

    original_threshold = threshold

    if threshold < min_threshold:
        print(f"*** Warning: Include path threshold {threshold} too "
              f"conservative for {mcu}, using safe minimum "
              f"{min_threshold} ***")
        threshold = min_threshold
    elif threshold > max_threshold:
        print(f"*** Warning: Include path threshold {threshold} exceeds "
              f"possible maximum for {mcu}, using {max_threshold} ***")
        threshold = max_threshold

    # Warning for conservative values (opposite of original - warn if too low)
    platform_default = get_platform_default_threshold(mcu)
    if threshold < platform_default * 0.7:  # More than 30% below max. default
        print(f"*** Info: Include path threshold {threshold} is conservative "
              f"compared to maximum default {platform_default} for "
              f"{mcu} ***")
        print("*** Consider using higher values for maximum performance ***")

    if original_threshold != threshold:
        print(f"Threshold adjusted from {original_threshold} to "
                        f"max. possible value {threshold} for {mcu}")

    return threshold


def get_include_path_threshold(env, config, current_env_section):
    """
    Determines Windows INCLUDE_PATH_LENGTH_THRESHOLD from various sources
    with priority order and max. possible  validation

    Priority order:
    1. Environment variable PLATFORMIO_INCLUDE_PATH_THRESHOLD
    2. Environment-specific setting in platformio.ini
    3. Global setting in [env] section
    4. Setting in [platformio] section
    5. MCU-specific max. possible default value

    Args:
        env: PlatformIO Environment
        config: Project Configuration
        current_env_section: Current environment section

    Returns:
        int: Validated max. threshold value
    """
    mcu = env.BoardConfig().get("build.mcu", "esp32")
    default_threshold = get_platform_default_threshold(mcu)
    setting_name = "custom_include_path_length_threshold"

    try:
        # 1. Check environment variable (highest priority)
        env_var = os.environ.get("PLATFORMIO_INCLUDE_PATH_THRESHOLD")
        if env_var:
            try:
                threshold = int(env_var)
                threshold = validate_threshold(threshold, mcu)
                print(f"*** Using environment variable max. possible include "
                      f"path threshold: {threshold} (MCU: {mcu}) ***")
                return threshold
            except ValueError:
                print(f"*** Warning: Invalid environment variable "
                      f"PLATFORMIO_INCLUDE_PATH_THRESHOLD='{env_var}', "
                      f"ignoring ***")

        # 2. Check environment-specific setting
        if config.has_option(current_env_section, setting_name):
            threshold = config.getint(current_env_section, setting_name)
            threshold = validate_threshold(threshold, mcu)
            print(f"*** Using environment-specific max. possible include "
                  f"path threshold: {threshold} (MCU: {mcu}) ***")
            return threshold

        # 3. Check global setting in [env] section
        if config.has_option("env", setting_name):
            threshold = config.getint("env", setting_name)
            threshold = validate_threshold(threshold, mcu)
            print(f"*** Using global [env] max. possible include path "
                  f"threshold: {threshold} (MCU: {mcu}) ***")
            return threshold

        # 4. Check setting in [platformio] section
        if config.has_option("platformio", setting_name):
            threshold = config.getint("platformio", setting_name)
            threshold = validate_threshold(threshold, mcu)
            print(f"*** Using [platformio] section max. possible include "
                  f"path threshold: {threshold} (MCU: {mcu}) ***")
            return threshold

        # 5. Use MCU-specific max. possible default value
        threshold = validate_threshold(default_threshold, mcu)
        if env.get("VERBOSE"):
            print(f"*** Using platform-specific max. possible default "
                  f"include path threshold: {threshold} (MCU: {mcu}) ***")

        return threshold

    except (ValueError, TypeError) as e:
        print(f"*** Warning: Invalid include path threshold value, using "
              f"max. possible platform default {default_threshold} for "
              f"{mcu}: {e} ***")
        return validate_threshold(default_threshold, mcu)


def get_threshold_info(env, config, current_env_section):
    """
    Helper function for debug information about max. possible threshold 
    configuration

    Args:
        env: PlatformIO Environment
        config: Project Configuration
        current_env_section: Current environment section

    Returns:
        dict: Information about threshold configuration
    """
    mcu = env.BoardConfig().get("build.mcu", "esp32")
    setting_name = "custom_include_path_length_threshold"

    info = {
        "mcu": mcu,
        "platform_default": get_platform_default_threshold(mcu),
        "env_variable": os.environ.get("PLATFORMIO_INCLUDE_PATH_THRESHOLD"),
        "env_specific": None,
        "global_env": None,
        "platformio_section": None,
        "final_threshold": None,
        "source": "bleeding_edge_platform_default",
        "is_bleeding_edge": True
    }

    # Collect all possible sources
    if config.has_option(current_env_section, setting_name):
        with suppress(ValueError):
            info["env_specific"] = config.getint(current_env_section,
                                                 setting_name)

    if config.has_option("env", setting_name):
        with suppress(ValueError):
            info["global_env"] = config.getint("env", setting_name)

    if config.has_option("platformio", setting_name):
        with suppress(ValueError):
            info["platformio_section"] = config.getint("platformio",
                                                       setting_name)

    # Determine final threshold and source
    info["final_threshold"] = get_include_path_threshold(env, config,
                                                         current_env_section)

    # Determine source
    if info["env_variable"]:
        info["source"] = "environment_variable"
    elif info["env_specific"] is not None:
        info["source"] = "env_specific"
    elif info["global_env"] is not None:
        info["source"] = "global_env"
    elif info["platformio_section"] is not None:
        info["source"] = "platformio_section"

    return info


# Cache class for frequently used paths
class PathCache:
    def __init__(self, platform, mcu):
        self.platform = platform
        self.mcu = mcu
        self._framework_dir = None
        self._framework_lib_dir = None
        self._sdk_dir = None

    @property
    def framework_dir(self):
        if self._framework_dir is None:
            self._framework_dir = self.platform.get_package_dir(
                "framework-arduinoespressif32")
        return self._framework_dir

    @property
    def framework_lib_dir(self):
        if self._framework_lib_dir is None:
            self._framework_lib_dir = self.platform.get_package_dir(
                "framework-arduinoespressif32-libs")
        return self._framework_lib_dir

    @property
    def sdk_dir(self):
        if self._sdk_dir is None:
            self._sdk_dir = fs.to_unix_path(
                join(self.framework_lib_dir, self.mcu, "include")
            )
        return self._sdk_dir


def check_and_warn_long_path_support():
    """Checks Windows long path support and issues warning if disabled"""
    with _PATH_SHORTENING_LOCK:  # Thread-safe access
        if not IS_WINDOWS or _PATH_SHORTENING_MESSAGES[
                'long_path_warning_shown']:
            return

        try:
            import winreg
            key = winreg.OpenKey(
                winreg.HKEY_LOCAL_MACHINE,
                r"SYSTEM\CurrentControlSet\Control\FileSystem"
            )
            value, _ = winreg.QueryValueEx(key, "LongPathsEnabled")
            winreg.CloseKey(key)

            if value != 1:
                print("*** WARNING: Windows Long Path Support is disabled ***")
                print("*** Enable it for better performance: ***")
                print("*** 1. Run as Administrator: gpedit.msc ***")
                print("*** 2. Navigate to: Computer Configuration > "
                      "Administrative Templates > System > Filesystem ***")
                print("*** 3. Enable 'Enable Win32 long paths' ***")
                print("*** OR run PowerShell as Admin: ***")
                print("*** New-ItemProperty -Path "
                      "'HKLM:\\SYSTEM\\CurrentControlSet\\Control\\FileSystem' "
                      "-Name 'LongPathsEnabled' -Value 1 -PropertyType DWORD "
                      "-Force ***")
                print("*** Restart required after enabling ***")
        except Exception:
            print("*** WARNING: Could not check Long Path Support status ***")
            print("*** Consider enabling Windows Long Path Support for "
                  "better performance ***")

        _PATH_SHORTENING_MESSAGES['long_path_warning_shown'] = True


# Secure deletion functions
def safe_delete_file(file_path: Union[str, Path],
                     force: bool = False) -> bool:
    """
    Secure file deletion

    Args:
        file_path: Path to file to be deleted
        force: Forces deletion even for write-protected files

    Returns:
        bool: True if successfully deleted
    """
    file_path = Path(file_path)

    try:
        # Check existence
        if not file_path.exists():
            return False

        # Remove write protection if necessary
        if force and not os.access(file_path, os.W_OK):
            file_path.chmod(0o666)

        # Delete file
        file_path.unlink()
        return True

    except PermissionError:
        return False
    except Exception as e:
        return False


def safe_delete_directory(dir_path: Union[str, Path]) -> bool:
    """
    Secure directory deletion
    """
    dir_path = Path(dir_path)

    try:
        if not dir_path.exists():
            return False

        shutil.rmtree(dir_path)
        return True

    except Exception as e:
        return False


def validate_platformio_path(path: Union[str, Path]) -> bool:
    """
    Enhanced validation for PlatformIO package paths
    """
    try:
        path = Path(path).resolve()
        path_str = str(path)

        # Must be within .platformio directory structure
        if ".platformio" not in path_str:
            return False

        # Must be a packages directory
        if "packages" not in path_str:
            return False

        # Must be framework-related
        framework_indicators = [
            "framework-arduinoespressif32",
            "framework-arduinoespressif32-libs"
        ]

        if not any(indicator in path_str for indicator in framework_indicators):
            return False

        # Must not be a critical system path
        critical_paths = ["/usr", "/bin", "/sbin", "/etc", "/boot",
                          "C:\\Windows", "C:\\Program Files"]
        return not any(critical in path_str for critical in critical_paths)

    except Exception as e:
        return False


def validate_deletion_path(path: Union[str, Path],
                           allowed_patterns: List[str]) -> bool:
    """
    Validates if a path can be safely deleted

    Args:
        path: Path to be checked
        allowed_patterns: Allowed path patterns

    Returns:
        bool: True if deletion is safe
    """
    path = Path(path).resolve()

    # Check against critical system paths
    critical_paths = [
        Path.home(),
        Path("/"),
        Path("C:\\") if IS_WINDOWS else None,
        Path("/usr"),
        Path("/etc"),
        Path("/bin"),
        Path("/sbin")
    ]

    for critical in filter(None, critical_paths):
        try:
            normalized_path = path.resolve()
            normalized_critical = critical.resolve()
            if (normalized_path == normalized_critical or
                    normalized_critical in normalized_path.parents):
                return False
        except (OSError, ValueError):
            # Path comparison failed, reject for safety
            return False

    # Check against allowed patterns
    path_str = str(path)
    is_allowed = any(pattern in path_str for pattern in allowed_patterns)

    return is_allowed


def safe_framework_cleanup():
    """Secure cleanup of Arduino Framework with enhanced error handling"""
    success = True

    # Framework directory cleanup
    if exists(FRAMEWORK_DIR):
        if validate_platformio_path(FRAMEWORK_DIR):
            if not safe_delete_directory(FRAMEWORK_DIR):
                print("Error removing framework")
                success = False

    # Framework libs directory cleanup
    if exists(FRAMEWORK_LIB_DIR):
        if validate_platformio_path(FRAMEWORK_LIB_DIR):
            if not safe_delete_directory(FRAMEWORK_LIB_DIR):
                print("Error removing framework libs")
                success = False

    return success


def safe_remove_sdkconfig_files():
    """Secure removal of SDKConfig files"""
    envs = [section.replace("env:", "") for section in config.sections()
            if section.startswith("env:")]
    for env_name in envs:
        file_path = join(project_dir, f"sdkconfig.{env_name}")
        if exists(file_path):
            safe_delete_file(file_path)


# Initialization
env = DefaultEnvironment()
pm = ToolPackageManager()
platform = env.PioPlatform()
config = env.GetProjectConfig()
board = env.BoardConfig()

# Cached values
mcu = board.get("build.mcu", "esp32")
pioenv = env["PIOENV"]
project_dir = env.subst("$PROJECT_DIR")
path_cache = PathCache(platform, mcu)
current_env_section = f"env:{pioenv}"

# Board configuration
board_sdkconfig = board.get("espidf.custom_sdkconfig", "")
entry_custom_sdkconfig = "\n"
flag_custom_sdkconfig = False
flag_custom_component_remove = False
flag_custom_component_add = False
flag_lib_ignore = False

if mcu == "esp32c2":
    flag_custom_sdkconfig = True

# pio lib_ignore check
if config.has_option(current_env_section, "lib_ignore"):
    flag_lib_ignore = True

# Custom Component remove check
if config.has_option(current_env_section, "custom_component_remove"):
    flag_custom_component_remove = True

# Custom SDKConfig check
if config.has_option(current_env_section, "custom_sdkconfig"):
    entry_custom_sdkconfig = env.GetProjectOption("custom_sdkconfig")
    flag_custom_sdkconfig = True

if board_sdkconfig:
    flag_custom_sdkconfig = True

extra_flags_raw = board.get("build.extra_flags", [])
if isinstance(extra_flags_raw, list):
    extra_flags = " ".join(extra_flags_raw).replace("-D", " ")
else:
    extra_flags = str(extra_flags_raw).replace("-D", " ")

framework_reinstall = False

FRAMEWORK_DIR = path_cache.framework_dir
FRAMEWORK_LIB_DIR = path_cache.framework_lib_dir

SConscript("_embed_files.py", exports="env")

flag_any_custom_sdkconfig = exists(join(
    platform.get_package_dir("framework-arduinoespressif32-libs"),
    "sdkconfig"))


def has_unicore_flags():
    """Check if any UNICORE flags are present in configuration"""
    return any(flag in extra_flags or flag in entry_custom_sdkconfig
               or flag in board_sdkconfig for flag in UNICORE_FLAGS)


# Esp32-solo1 libs settings
if flag_custom_sdkconfig and has_unicore_flags():
    if not env.get('BUILD_UNFLAGS'):  # Initialize if not set
        env['BUILD_UNFLAGS'] = []

    build_unflags = (" ".join(env['BUILD_UNFLAGS']) +
                     " -mdisable-hardware-atomics -ustart_app_other_cores")
    new_build_unflags = build_unflags.split()
    env.Replace(BUILD_UNFLAGS=new_build_unflags)


def get_MD5_hash(phrase):
    return hashlib.md5(phrase.encode('utf-8')).hexdigest()[:16]


def matching_custom_sdkconfig():
    """Checks if current environment matches existing sdkconfig"""
    cust_sdk_is_present = False

    if not flag_any_custom_sdkconfig:
        return True, cust_sdk_is_present

    last_sdkconfig_path = join(project_dir, "sdkconfig.defaults")
    if not exists(last_sdkconfig_path):
        return False, cust_sdk_is_present

    if not flag_custom_sdkconfig:
        return False, cust_sdk_is_present

    try:
        with open(last_sdkconfig_path) as src:
            line = src.readline()
            if line.startswith("# TASMOTA__"):
                cust_sdk_is_present = True
                custom_options = entry_custom_sdkconfig
                expected_hash = get_MD5_hash(custom_options.strip() + mcu)
                if line.split("__")[1].strip() == expected_hash:
                    return True, cust_sdk_is_present
    except (IOError, IndexError):
        pass

    return False, cust_sdk_is_present


def check_reinstall_frwrk():
    if not flag_custom_sdkconfig and flag_any_custom_sdkconfig:
        # case custom sdkconfig exists and an env without "custom_sdkconfig"
        return True

    if flag_custom_sdkconfig:
        matching_sdkconfig, _ = matching_custom_sdkconfig()
        if not matching_sdkconfig:
            # check if current custom sdkconfig is different from existing
            return True

    return False


def call_compile_libs():
    print(f"*** Compile Arduino IDF libs for {pioenv} ***")
    SConscript("espidf.py")


FRAMEWORK_SDK_DIR = path_cache.sdk_dir
IS_INTEGRATION_DUMP = env.IsIntegrationDump()


def is_framework_subfolder(potential_subfolder):
    """Check if a path is a subfolder of the framework SDK directory"""
    # carefully check before change this function
    if not isabs(potential_subfolder):
        return False
    if (splitdrive(FRAMEWORK_SDK_DIR)[0] !=
            splitdrive(potential_subfolder)[0]):
        return False
    return (commonpath([FRAMEWORK_SDK_DIR]) ==
            commonpath([FRAMEWORK_SDK_DIR, potential_subfolder]))


# Performance optimization with caching
def calculate_include_path_length(includes):
    """Calculate total character count of all include paths with caching"""
    if not hasattr(calculate_include_path_length, '_cache'):
        calculate_include_path_length._cache = {}

    cache_key = tuple(includes)
    if cache_key not in calculate_include_path_length._cache:
        calculate_include_path_length._cache[cache_key] = sum(
            len(str(inc)) for inc in includes)

    return calculate_include_path_length._cache[cache_key]


def analyze_path_distribution(includes):
    """Analyze the distribution of include path lengths for optimization 
    insights"""
    if not includes:
        return {}

    lengths = [len(str(inc)) for inc in includes]
    framework_lengths = [len(str(inc)) for inc in includes
                         if is_framework_subfolder(inc)]

    return {
        'total_paths': len(includes),
        'total_length': sum(lengths),
        'average_length': sum(lengths) / len(lengths),
        'max_length': max(lengths),
        'min_length': min(lengths),
        'framework_paths': len(framework_lengths),
        'framework_total_length': sum(framework_lengths),
        'framework_avg_length': (sum(framework_lengths) /
                                 len(framework_lengths)
                                 if framework_lengths else 0)
    }


def debug_framework_paths(env, include_count, total_length):
    """Debug framework paths to understand the issue (verbose mode only)"""
    if not env.get("VERBOSE"):
        return

    print("*** Debug Framework Paths ***")
    print(f"*** MCU: {mcu} ***")
    print(f"*** FRAMEWORK_DIR: {FRAMEWORK_DIR} ***")
    print(f"*** FRAMEWORK_SDK_DIR: {FRAMEWORK_SDK_DIR} ***")
    print(f"*** SDK exists: {exists(FRAMEWORK_SDK_DIR)} ***")
    print(f"*** Include count: {include_count} ***")
    print(f"*** Total path length: {total_length} ***")

    includes = env.get("CPPPATH", [])
    framework_count = 0
    longest_paths = sorted(includes, key=len, reverse=True)[:5]

    print("*** Longest include paths: ***")
    for i, inc in enumerate(longest_paths):
        is_fw = is_framework_subfolder(inc)
        if is_fw:
            framework_count += 1
        print(f"***   {i+1}: {inc} (length: {len(str(inc))}) -> "
              f"Framework: {is_fw} ***")

    print(f"*** Framework includes found: {framework_count}/"
          f"{len(includes)} ***")

    # Show path distribution analysis
    analysis = analyze_path_distribution(includes)
    print(f"*** Path Analysis: Avg={analysis.get('average_length', 0):.1f}, "
          f"Max={analysis.get('max_length', 0)}, "
          f"Framework Avg={analysis.get('framework_avg_length', 0):.1f} ***")


def apply_include_shortening(env, node, includes, total_length):
    """Applies include path shortening technique"""
    env_get = env.get
    to_unix_path = fs.to_unix_path
    ccflags = env["CCFLAGS"]
    asflags = env["ASFLAGS"]

    includes = [to_unix_path(inc) for inc in env_get("CPPPATH", [])]
    shortened_includes = []
    generic_includes = []

    original_length = total_length
    saved_chars = 0

    for inc in includes:
        if is_framework_subfolder(inc):
            relative_path = to_unix_path(relpath(inc, FRAMEWORK_SDK_DIR))
            shortened_path = "-iwithprefix/" + relative_path
            shortened_includes.append(shortened_path)

            # Calculate character savings
            # Original: full path in -I flag
            # New: -iprefix + shortened relative path
            original_chars = len(f"-I{inc}")
            new_chars = len(shortened_path)
            saved_chars += max(0, original_chars - new_chars)
        else:
            generic_includes.append(inc)

    # Show result message only once with thread safety
    with _PATH_SHORTENING_LOCK:
        if not _PATH_SHORTENING_MESSAGES['shortening_applied']:
            if shortened_includes:
                # Each -I is 2 chars
                removed_i_flags = len(shortened_includes) * 2
                new_total_length = (original_length - saved_chars +
                                    len(f"-iprefix{FRAMEWORK_SDK_DIR}") -
                                    removed_i_flags)
                print(f"*** Applied include path shortening for "
                      f"{len(shortened_includes)} framework paths ***")
                print(f"*** Path length reduced from {original_length} to "
                      f"~{new_total_length} characters ***")
                print(f"*** Estimated savings: {saved_chars} characters ***")
            else:
                if not _PATH_SHORTENING_MESSAGES[
                        'no_framework_paths_warning']:
                    print("*** Warning: Path length high but no framework "
                          "paths found for shortening ***")
                    print("*** This may indicate an architecture-specific "
                          "issue ***")
                    print("*** Run with -v (verbose) for detailed path "
                          "analysis ***")
                    _PATH_SHORTENING_MESSAGES[
                        'no_framework_paths_warning'] = True
            _PATH_SHORTENING_MESSAGES['shortening_applied'] = True

    common_flags = ["-iprefix", FRAMEWORK_SDK_DIR] + shortened_includes

    return env.Object(
        node,
        CPPPATH=generic_includes,
        CCFLAGS=ccflags + common_flags,
        ASFLAGS=asflags + common_flags,
    )


def smart_include_length_shorten(env, node):
    """
    Include path shortening based on max. performance configurable threshold 
    with enhanced MCU support
    Uses aggressive thresholds for maximum performance
    """
    if IS_INTEGRATION_DUMP:
        return node

    if not IS_WINDOWS:
        return env.Object(node)

    # Get dynamically configurable bleeding edge threshold
    include_path_threshold = get_include_path_threshold(env, config,
                                                        current_env_section)

    check_and_warn_long_path_support()

    includes = env.get("CPPPATH", [])
    include_count = len(includes)
    total_path_length = calculate_include_path_length(includes)

    # Debug information in verbose mode
    if env.get("VERBOSE"):
        debug_framework_paths(env, include_count, total_path_length)

        # Extended debug information about maximum edge threshold 
        # configuration
        threshold_info = get_threshold_info(env, config, current_env_section)
        print("*** Maximum Threshold Configuration Debug ***")
        print(f"***   MCU: {threshold_info['mcu']} ***")
        print(f"***   Maximum Platform Default: "
              f"{threshold_info['platform_default']} ***")
        print(f"***   Final maximum Threshold: "
              f"{threshold_info['final_threshold']} ***")
        print(f"***   Source: {threshold_info['source']} ***")
        print("***   Performance Mode: Maximum Aggressive ***")
        if threshold_info['env_variable']:
            print(f"***   Env Variable: {threshold_info['env_variable']} ***")
        if threshold_info['env_specific']:
            print(f"***   Env Specific: {threshold_info['env_specific']} ***")
        if threshold_info['global_env']:
            print(f"***   Global Env: {threshold_info['global_env']} ***")
        if threshold_info['platformio_section']:
            print(f"***   PlatformIO Section: "
                  f"{threshold_info['platformio_section']} ***")

    # Use the configurable and validated bleeding edge threshold
    if total_path_length <= include_path_threshold:
        return env.Object(node)

    return apply_include_shortening(env, node, includes, total_path_length)


def get_frameworks_in_current_env():
    """Determines the frameworks of the current environment"""
    if "framework" in config.options(current_env_section):
        return config.get(current_env_section, "framework", "")
    return []


# Framework check
current_env_frameworks = get_frameworks_in_current_env()
if "arduino" in current_env_frameworks and "espidf" in current_env_frameworks:
    # Arduino as component is set, switch off Hybrid compile
    flag_custom_sdkconfig = False

# Framework reinstallation if required - Enhanced with secure deletion and 
# error handling
if check_reinstall_frwrk():
    # Secure removal of SDKConfig files
    safe_remove_sdkconfig_files()

    print("*** Reinstall Arduino framework ***")

    # Secure framework cleanup with enhanced error handling
    if safe_framework_cleanup():
        arduino_frmwrk_url = str(platform.get_package_spec(
            "framework-arduinoespressif32")).split("uri=", 1)[1][:-1]
        arduino_frmwrk_lib_url = str(platform.get_package_spec(
            "framework-arduinoespressif32-libs")).split("uri=", 1)[1][:-1]
        pm.install(arduino_frmwrk_url)
        pm.install(arduino_frmwrk_lib_url)

        if flag_custom_sdkconfig:
            call_compile_libs()
            flag_custom_sdkconfig = False
    else:
        print("Framework cleanup failed - installation aborted")
        sys.exit(1)

if flag_custom_sdkconfig and not flag_any_custom_sdkconfig:
    call_compile_libs()

# Main logic for Arduino Framework
pioframework = env.subst("$PIOFRAMEWORK")
arduino_lib_compile_flag = env.subst("$ARDUINO_LIB_COMPILE_FLAG")

if ("arduino" in pioframework and "espidf" not in pioframework and
        arduino_lib_compile_flag in ("Inactive", "True")):

    # try to remove not needed include path if an lib_ignore entry exists
    from component_manager import ComponentManager
    component_manager = ComponentManager(env)
    component_manager.handle_component_settings()
    silent_action = env.Action(component_manager.restore_pioarduino_build_py)
    # hack to silence scons command output
    silent_action.strfunction = lambda target, source, env: ''
    env.AddPostAction("checkprogsize", silent_action)

    if IS_WINDOWS:
        env.AddBuildMiddleware(smart_include_length_shorten)

    build_script_path = join(FRAMEWORK_DIR, "tools", "pioarduino-build.py")
    SConscript(build_script_path)
