# SPDX-License-Identifier: Apache-2.0
# Copyright 2019 The Meson development team

from __future__ import annotations
from pathlib import Path, PurePath, PureWindowsPath
import hashlib
import os
import typing as T

from . import ExtensionModule, ModuleReturnValue, ModuleInfo
from .. import mlog
from ..build import BuildTarget, CustomTarget, CustomTargetIndex, InvalidArguments
from ..interpreter.type_checking import INSTALL_KW, INSTALL_MODE_KW, INSTALL_TAG_KW, NoneType
from ..interpreterbase import FeatureNew, KwargInfo, typed_kwargs, typed_pos_args, noKwargs
from ..mesonlib import File, MesonException, has_path_sep, path_is_in_root, relpath

if T.TYPE_CHECKING:
    from . import ModuleState
    from ..build import BuildTargetTypes
    from ..interpreter import Interpreter
    from ..interpreterbase import TYPE_kwargs
    from ..mesonlib import FileOrString, FileMode

    from typing_extensions import TypedDict

    class ReadKwArgs(TypedDict):
        """Keyword Arguments for fs.read."""

        encoding: str

    class CopyKw(TypedDict):

        """Kwargs for fs.copy"""

        install: bool
        install_dir: T.Optional[str]
        install_mode: FileMode
        install_tag: T.Optional[str]


class FSModule(ExtensionModule):

    INFO = ModuleInfo('fs', '0.53.0')

    def __init__(self, interpreter: 'Interpreter') -> None:
        super().__init__(interpreter)
        self.methods.update({
            'as_posix': self.as_posix,
            'copyfile': self.copyfile,
            'exists': self.exists,
            'expanduser': self.expanduser,
            'hash': self.hash,
            'is_absolute': self.is_absolute,
            'is_dir': self.is_dir,
            'is_file': self.is_file,
            'is_samepath': self.is_samepath,
            'is_symlink': self.is_symlink,
            'name': self.name,
            'parent': self.parent,
            'read': self.read,
            'relative_to': self.relative_to,
            'replace_suffix': self.replace_suffix,
            'size': self.size,
            'stem': self.stem,
        })

    def _absolute_dir(self, state: 'ModuleState', arg: 'FileOrString') -> Path:
        """
        make an absolute path from a relative path, WITHOUT resolving symlinks
        """
        if isinstance(arg, File):
            return Path(arg.absolute_path(state.source_root, state.environment.get_build_dir()))
        return Path(state.source_root) / Path(state.subdir) / Path(arg).expanduser()

    @staticmethod
    def _obj_to_path(feature_new_prefix: str, obj: T.Union[FileOrString, BuildTargetTypes], state: ModuleState) -> PurePath:
        if isinstance(obj, str):
            return PurePath(obj)

        if isinstance(obj, File):
            FeatureNew(f'{feature_new_prefix} with file', '0.59.0').use(state.subproject, location=state.current_node)
            return PurePath(str(obj))

        FeatureNew(f'{feature_new_prefix} with build_tgt, custom_tgt, and custom_idx', '1.4.0').use(state.subproject, location=state.current_node)
        return PurePath(state.backend.get_target_filename(obj))

    def _resolve_dir(self, state: 'ModuleState', arg: 'FileOrString') -> Path:
        """
        resolves symlinks and makes absolute a directory relative to calling meson.build,
        if not already absolute
        """
        path = self._absolute_dir(state, arg)
        try:
            # accommodate unresolvable paths e.g. symlink loops
            path = path.resolve()
        except Exception:
            # return the best we could do
            pass
        return path

    @noKwargs
    @FeatureNew('fs.expanduser', '0.54.0')
    @typed_pos_args('fs.expanduser', str)
    def expanduser(self, state: 'ModuleState', args: T.Tuple[str], kwargs: T.Dict[str, T.Any]) -> str:
        return str(Path(args[0]).expanduser())

    @noKwargs
    @FeatureNew('fs.is_absolute', '0.54.0')
    @typed_pos_args('fs.is_absolute', (str, File))
    def is_absolute(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: T.Dict[str, T.Any]) -> bool:
        if isinstance(args[0], File):
            FeatureNew('fs.is_absolute with file', '0.59.0').use(state.subproject, location=state.current_node)
        return PurePath(str(args[0])).is_absolute()

    @noKwargs
    @FeatureNew('fs.as_posix', '0.54.0')
    @typed_pos_args('fs.as_posix', str)
    def as_posix(self, state: 'ModuleState', args: T.Tuple[str], kwargs: T.Dict[str, T.Any]) -> str:
        r"""
        this function assumes you are passing a Windows path, even if on a Unix-like system
        and so ALL '\' are turned to '/', even if you meant to escape a character
        """
        return PureWindowsPath(args[0]).as_posix()

    @noKwargs
    @typed_pos_args('fs.exists', str)
    def exists(self, state: 'ModuleState', args: T.Tuple[str], kwargs: T.Dict[str, T.Any]) -> bool:
        return self._resolve_dir(state, args[0]).exists()

    @noKwargs
    @typed_pos_args('fs.is_symlink', (str, File))
    def is_symlink(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: T.Dict[str, T.Any]) -> bool:
        if isinstance(args[0], File):
            FeatureNew('fs.is_symlink with file', '0.59.0').use(state.subproject, location=state.current_node)
        return self._absolute_dir(state, args[0]).is_symlink()

    @noKwargs
    @typed_pos_args('fs.is_file', str)
    def is_file(self, state: 'ModuleState', args: T.Tuple[str], kwargs: T.Dict[str, T.Any]) -> bool:
        return self._resolve_dir(state, args[0]).is_file()

    @noKwargs
    @typed_pos_args('fs.is_dir', str)
    def is_dir(self, state: 'ModuleState', args: T.Tuple[str], kwargs: T.Dict[str, T.Any]) -> bool:
        return self._resolve_dir(state, args[0]).is_dir()

    @noKwargs
    @typed_pos_args('fs.hash', (str, File), str)
    def hash(self, state: 'ModuleState', args: T.Tuple['FileOrString', str], kwargs: T.Dict[str, T.Any]) -> str:
        if isinstance(args[0], File):
            FeatureNew('fs.hash with file', '0.59.0').use(state.subproject, location=state.current_node)
        file = self._resolve_dir(state, args[0])
        if not file.is_file():
            raise MesonException(f'{file} is not a file and therefore cannot be hashed')
        try:
            h = hashlib.new(args[1])
        except ValueError:
            raise MesonException('hash algorithm {} is not available'.format(args[1]))
        mlog.debug('computing {} sum of {} size {} bytes'.format(args[1], file, file.stat().st_size))
        h.update(file.read_bytes())
        return h.hexdigest()

    @noKwargs
    @typed_pos_args('fs.size', (str, File))
    def size(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: T.Dict[str, T.Any]) -> int:
        if isinstance(args[0], File):
            FeatureNew('fs.size with file', '0.59.0').use(state.subproject, location=state.current_node)
        file = self._resolve_dir(state, args[0])
        if not file.is_file():
            raise MesonException(f'{file} is not a file and therefore cannot be sized')
        try:
            return file.stat().st_size
        except ValueError:
            raise MesonException('{} size could not be determined'.format(args[0]))

    @noKwargs
    @typed_pos_args('fs.is_samepath', (str, File), (str, File))
    def is_samepath(self, state: 'ModuleState', args: T.Tuple['FileOrString', 'FileOrString'], kwargs: T.Dict[str, T.Any]) -> bool:
        if isinstance(args[0], File) or isinstance(args[1], File):
            FeatureNew('fs.is_samepath with file', '0.59.0').use(state.subproject, location=state.current_node)
        file1 = self._resolve_dir(state, args[0])
        file2 = self._resolve_dir(state, args[1])
        if not file1.exists():
            return False
        if not file2.exists():
            return False
        try:
            return file1.samefile(file2)
        except OSError:
            return False

    @noKwargs
    @typed_pos_args('fs.replace_suffix', (str, File, CustomTarget, CustomTargetIndex, BuildTarget), str)
    def replace_suffix(self, state: 'ModuleState', args: T.Tuple[T.Union[FileOrString, BuildTargetTypes], str], kwargs: T.Dict[str, T.Any]) -> str:
        path = self._obj_to_path('fs.replace_suffix', args[0], state)
        return str(path.with_suffix(args[1]))

    @noKwargs
    @typed_pos_args('fs.parent', (str, File, CustomTarget, CustomTargetIndex, BuildTarget))
    def parent(self, state: 'ModuleState', args: T.Tuple[T.Union[FileOrString, BuildTargetTypes]], kwargs: T.Dict[str, T.Any]) -> str:
        path = self._obj_to_path('fs.parent', args[0], state)
        return str(path.parent)

    @noKwargs
    @typed_pos_args('fs.name', (str, File, CustomTarget, CustomTargetIndex, BuildTarget))
    def name(self, state: 'ModuleState', args: T.Tuple[T.Union[FileOrString, BuildTargetTypes]], kwargs: T.Dict[str, T.Any]) -> str:
        path = self._obj_to_path('fs.name', args[0], state)
        return str(path.name)

    @noKwargs
    @typed_pos_args('fs.stem', (str, File, CustomTarget, CustomTargetIndex, BuildTarget))
    @FeatureNew('fs.stem', '0.54.0')
    def stem(self, state: 'ModuleState', args: T.Tuple[T.Union[FileOrString, BuildTargetTypes]], kwargs: T.Dict[str, T.Any]) -> str:
        path = self._obj_to_path('fs.stem', args[0], state)
        return str(path.stem)

    @FeatureNew('fs.read', '0.57.0')
    @typed_pos_args('fs.read', (str, File))
    @typed_kwargs('fs.read', KwargInfo('encoding', str, default='utf-8'))
    def read(self, state: 'ModuleState', args: T.Tuple['FileOrString'], kwargs: 'ReadKwArgs') -> str:
        """Read a file from the source tree and return its value as a decoded
        string.

        If the encoding is not specified, the file is assumed to be utf-8
        encoded. Paths must be relative by default (to prevent accidents) and
        are forbidden to be read from the build directory (to prevent build
        loops)
        """
        path = args[0]
        encoding = kwargs['encoding']
        src_dir = state.environment.source_dir
        sub_dir = state.subdir
        build_dir = state.environment.get_build_dir()

        if isinstance(path, File):
            if path.is_built:
                raise MesonException(
                    'fs.read does not accept built files() objects')
            path = os.path.join(src_dir, path.relative_name())
        else:
            if sub_dir:
                src_dir = os.path.join(src_dir, sub_dir)
            path = os.path.join(src_dir, path)

        path = os.path.abspath(path)
        if path_is_in_root(Path(path), Path(build_dir), resolve=True):
            raise MesonException('path must not be in the build tree')
        try:
            with open(path, encoding=encoding) as f:
                data = f.read()
        except FileNotFoundError:
            raise MesonException(f'File {args[0]} does not exist.')
        except UnicodeDecodeError:
            raise MesonException(f'decoding failed for {args[0]}')
        # Reconfigure when this file changes as it can contain data used by any
        # part of the build configuration (e.g. `project(..., version:
        # fs.read_file('VERSION')` or `configure_file(...)`
        self.interpreter.add_build_def_file(path)
        return data

    @FeatureNew('fs.copyfile', '0.64.0')
    @typed_pos_args('fs.copyfile', (File, str), optargs=[str])
    @typed_kwargs(
        'fs.copyfile',
        INSTALL_KW,
        INSTALL_MODE_KW,
        INSTALL_TAG_KW,
        KwargInfo('install_dir', (str, NoneType)),
    )
    def copyfile(self, state: ModuleState, args: T.Tuple[FileOrString, T.Optional[str]],
                 kwargs: CopyKw) -> ModuleReturnValue:
        """Copy a file into the build directory at build time."""
        if kwargs['install'] and not kwargs['install_dir']:
            raise InvalidArguments('"install_dir" must be specified when "install" is true')

        src = self.interpreter.source_strings_to_files([args[0]])[0]

        # The input is allowed to have path separators, but the output may not,
        # so use the basename for the default case
        dest = args[1] if args[1] else os.path.basename(src.fname)
        if has_path_sep(dest):
            raise InvalidArguments('Destination path may not have path separators')

        ct = CustomTarget(
            dest,
            state.subdir,
            state.subproject,
            state.environment,
            state.environment.get_build_command() + ['--internal', 'copy', '@INPUT@', '@OUTPUT@'],
            [src],
            [dest],
            build_by_default=True,
            install=kwargs['install'],
            install_dir=[kwargs['install_dir']],
            install_mode=kwargs['install_mode'],
            install_tag=[kwargs['install_tag']],
            backend=state.backend,
            description='Copying file {}',
        )

        return ModuleReturnValue(ct, [ct])

    @FeatureNew('fs.relative_to', '1.3.0')
    @typed_pos_args('fs.relative_to', (str, File, CustomTarget, CustomTargetIndex, BuildTarget), (str, File, CustomTarget, CustomTargetIndex, BuildTarget))
    @noKwargs
    def relative_to(self, state: ModuleState, args: T.Tuple[T.Union[FileOrString, BuildTargetTypes], T.Union[FileOrString, BuildTargetTypes]], kwargs: TYPE_kwargs) -> str:
        def to_path(arg: T.Union[FileOrString, CustomTarget, CustomTargetIndex, BuildTarget]) -> str:
            if isinstance(arg, File):
                return arg.absolute_path(state.environment.source_dir, state.environment.build_dir)
            elif isinstance(arg, (CustomTarget, CustomTargetIndex, BuildTarget)):
                return state.backend.get_target_filename_abs(arg)
            else:
                return os.path.join(state.environment.source_dir, state.subdir, arg)

        t = to_path(args[0])
        f = to_path(args[1])

        return relpath(t, f)


def initialize(*args: T.Any, **kwargs: T.Any) -> FSModule:
    return FSModule(*args, **kwargs)
