# Copyright 2020 The Pigweed Authors
#
# 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
#
#     https://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.
"""Install and check status of teensy-core."""

import json
import logging
import re
import subprocess
import tempfile
from pathlib import Path
from typing import Sequence

from pw_arduino_build import core_installer

import pw_package.package_manager

_LOG: logging.Logger = logging.getLogger(__name__)


class ArduinoCore(pw_package.package_manager.Package):
    """Install and check status of arduino cores."""
    def __init__(self, core_name, *args, **kwargs):
        super().__init__(*args, name=core_name, **kwargs)

    def status(self, path: Path) -> bool:
        return (path / 'hardware').is_dir()

    def populate_download_cache_from_cipd(self, path: Path) -> None:
        """Check for arduino core availability in pigweed_internal cipd."""
        package_path = path.parent.resolve()
        core_name = self.name
        core_cache_path = package_path / ".cache" / core_name
        core_cache_path.mkdir(parents=True, exist_ok=True)

        cipd_package_subpath = "pigweed_internal/third_party/"
        cipd_package_subpath += core_name
        cipd_package_subpath += "/${platform}"

        # Check if teensy cipd package is readable

        with tempfile.NamedTemporaryFile(prefix='cipd',
                                         delete=True) as temp_json:
            cipd_acl_check_command = [
                "cipd",
                "acl-check",
                cipd_package_subpath,
                "-reader",
                "-json-output",
                temp_json.name,
            ]
            subprocess.run(cipd_acl_check_command, capture_output=True)
            # Return if no packages are readable.
            if not json.load(temp_json)['result']:
                return

        def _run_command(command):
            _LOG.debug("Running: `%s`", " ".join(command))
            result = subprocess.run(command, capture_output=True)
            _LOG.debug("Output:\n%s",
                       result.stdout.decode() + result.stderr.decode())

        _run_command(["cipd", "init", "-force", core_cache_path.as_posix()])
        _run_command([
            "cipd", "install", cipd_package_subpath, "-root",
            core_cache_path.as_posix(), "-force"
        ])

        _LOG.debug(
            "Available Cache Files:\n%s",
            "\n".join([p.as_posix() for p in core_cache_path.glob("*")]))

    def install(self, path: Path) -> None:
        self.populate_download_cache_from_cipd(path)

        if self.status(path):
            return
        # Otherwise delete current version and reinstall
        core_installer.install_core(path.parent.resolve().as_posix(),
                                    self.name)

    def info(self, path: Path) -> Sequence[str]:
        packages_root = path.parent.resolve()
        arduino_package_path = path
        arduino_package_name = None

        message = [
            f'{self.name} currently installed in: {path}',
        ]
        # Make gn args sample copy/paste-able by omitting the starting timestamp
        # and INF log on each line.
        message_gn_args = [
            'Enable by running "gn args out" and adding these lines:',
            f'  pw_arduino_build_CORE_PATH = "{packages_root}"',
            f'  pw_arduino_build_CORE_NAME = "{self.name}"'
        ]

        # Search for first valid 'package/version' directory
        for hardware_dir in [
                path for path in (path / 'hardware').iterdir()
                if path.is_dir()
        ]:
            if path.name in ["arduino", "tools"]:
                continue
            for subdir in [
                    path for path in hardware_dir.iterdir() if path.is_dir()
            ]:
                if subdir.name == 'avr' or re.match(r'[0-9.]+', subdir.name):
                    arduino_package_name = f'{hardware_dir.name}/{subdir.name}'
                    break

        if arduino_package_name:
            message_gn_args += [
                f'  pw_arduino_build_PACKAGE_NAME = "{arduino_package_name}"',
                '  pw_arduino_build_BOARD = "BOARD_NAME"'
            ]
            message += ["\n".join(message_gn_args)]
            message += [
                'Where BOARD_NAME is any supported board.',
                # Have arduino_builder command appear on it's own line.
                'List available boards by running:\n'
                '  arduino_builder '
                f'--arduino-package-path {arduino_package_path} '
                f'--arduino-package-name {arduino_package_name} list-boards'
            ]
        return message


for arduino_core_name in core_installer.supported_cores():
    pw_package.package_manager.register(ArduinoCore,
                                        core_name=arduino_core_name)
