'''
Windows utils for simple things in other OSes, such as: finding anything in
$env:LOCALAPPDATA (in case App exe is not in $env:Path)
'''

import os
from opencos import eda_config
from opencos.utils import subprocess_helpers

IS_WINDOWS = subprocess_helpers.IS_WINDOWS


def get_windows_tool_info( # pylint: disable=dangerous-default-value
        app_name: str, prefer_exes: list = []
) -> dict:
    """
    Resolves the actual binary path and version from a Windows electron app.
    app_name: e.g., 'Cognichip'

    Will look in:
      -- $LOCALAPPDATA
      -- $PROGRAMFILES
      -- ./Programs/ for each
    """
    ret = {}
    if not IS_WINDOWS:
        return ret

    local_app_data = os.environ.get('LOCALAPPDATA', '')
    program_files = os.environ.get('PROGRAMFILES', '')

    try_dirs = [
        local_app_data,
        os.path.join(local_app_data, 'Programs'),
        program_files,
        os.path.join(program_files, 'Programs')
    ]

    base_path = ''
    for x in try_dirs:
        if x:
            base_path = os.path.join(x, app_name)
            if os.path.isdir(base_path):
                break

    ret.update({
        'base_path': {
            'value': base_path,
            'exists': os.path.exists(base_path)
        }
    })

    if not os.path.exists(base_path):
        return ret

    # 1. Resolve Executable (Replaces shutil.which), assumes ./bin/ and ./
    # we prefer something in ./bin/tool.cmd, those tend to swallow a few
    # otherwise stdout/stderr on startup.
    exe_path = ''
    found_exe = False
    for _try_dir in ['bin', '']:
        if found_exe:
            break
        for _try_exe_name in prefer_exes + [app_name, f'{app_name}.EXE', f'{app_name}.CMD']:
            exe_path = os.path.join(base_path, _try_dir, _try_exe_name)
            if os.path.exists(exe_path) and \
               os.access(exe_path, os.F_OK) and \
               os.access(exe_path, os.X_OK):
                found_exe = True
                break

    if not found_exe:
        exe_path = ''

    # 2. Resolve Version via product.json
    product_json_path = os.path.join(base_path, 'resources', 'app', 'product.json')

    # We can get the exe shortname from product.json:
    # key = win32ShellNameShort
    # but that doesn't tell us it's in ./bin

    ret.update({
        'product_json_path': {
            'value': product_json_path,
            'exists': os.path.exists(product_json_path)
        },
    })

    # We can't get the version yet unless we open the product_json_path
    ret.update({
        "bin": exe_path,
        "metadata": product_json_path if os.path.exists(product_json_path) else ''
    })
    return ret


def get_tool_exe_from_config(config: dict, tool: str) -> str:
    """
    Returns exe path for 'tool', looking in LOCALAPPDATA, aka
    C:\\Users\\$USER\\AppData\\Local

    If not windows, reverts to the first exe in config.
    tool -- this is the opencos-eda tool name, such as 'verilator',
    from the --tool=TOOL arg, or auto-found.
    """

    tool_cfg = config.get('tools', {}).get(tool, {})
    exe_list = eda_config.tool_get_exe_list(tool=tool, config=config)
    first_exe = exe_list[0]

    if IS_WINDOWS:
        app_name = tool_cfg.get('windows-app-name', '')
        if not app_name:
            app_name = tool_cfg.get('app-name', '')
        if not app_name:
            app_name = tool_cfg.get('macos-app-name', '')

        prefer_exes = tool_cfg.get('windows-prefer-exes', [])
        if exe_list:
            prefer_exes = exe_list + prefer_exes
        if app_name:
            data = get_windows_tool_info(app_name, prefer_exes=prefer_exes)
            if e := data.get('bin', ''):
                first_exe = e

    return first_exe
