# Copyright 2021-2023 Google LLC
#
# 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.

# -----------------------------------------------------------------------------
# Imports
# -----------------------------------------------------------------------------
import logging
import pathlib
import urllib.error
import urllib.request

import click

import bumble.logging
from bumble.colors import color
from bumble.drivers import rtk
from bumble.tools import rtk_util

# -----------------------------------------------------------------------------
# Logging
# -----------------------------------------------------------------------------
logger = logging.getLogger(__name__)


# -----------------------------------------------------------------------------
# Constants
# -----------------------------------------------------------------------------
LINUX_KERNEL_GIT_SOURCE = (
    "https://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git/plain/rtl_bt",
    False,
)
REALTEK_OPENSOURCE_SOURCE = (
    "https://github.com/Realtek-OpenSource/android_hardware_realtek/raw/rtk1395/bt/rtkbt/Firmware/BT",
    True,
)
LINUX_FROM_SCRATCH_SOURCE = (
    "https://anduin.linuxfromscratch.org/sources/linux-firmware/rtl_bt",
    False,
)


# -----------------------------------------------------------------------------
# Functions
# -----------------------------------------------------------------------------
def download_file(base_url, name, remove_suffix):
    if remove_suffix:
        name = name.replace(".bin", "")

    url = f"{base_url}/{name}"
    logger.debug(f"downloading {url}")
    request = urllib.request.Request(url, data=None, headers={"User-Agent": "Bumble"})
    with urllib.request.urlopen(request) as file:
        data = file.read()
        print(f"Downloaded {name}: {len(data)} bytes")
        return data


# -----------------------------------------------------------------------------
@click.command
@click.option(
    "--output-dir",
    default="",
    help="Output directory where the files will be saved. Defaults to the OS-specific"
    "app data dir, which the driver will check when trying to find firmware",
    show_default=True,
)
@click.option(
    "--source",
    type=click.Choice(["linux-kernel", "realtek-opensource", "linux-from-scratch"]),
    default="linux-kernel",
    show_default=True,
)
@click.option("--single", help="Only download a single image set, by its base name")
@click.option("--force", is_flag=True, help="Overwrite files if they already exist")
@click.option("--parse", is_flag=True, help="Parse the FW image after saving")
def main(output_dir, source, single, force, parse):
    """Download RTK firmware images and configs."""
    bumble.logging.setup_basic_logging()

    # Check that the output dir exists
    if output_dir == '':
        output_dir = rtk.rtk_firmware_dir()
    else:
        output_dir = pathlib.Path(output_dir)
    if not output_dir.is_dir():
        print("Output dir does not exist or is not a directory")
        return

    base_url, remove_suffix = {
        "linux-kernel": LINUX_KERNEL_GIT_SOURCE,
        "realtek-opensource": REALTEK_OPENSOURCE_SOURCE,
        "linux-from-scratch": LINUX_FROM_SCRATCH_SOURCE,
    }[source]

    print("Downloading")
    print(color("FROM:", "green"), base_url)
    print(color("TO:", "green"), output_dir)

    if single:
        images = [(f"{single}_fw.bin", f"{single}_config.bin", True)]
    else:
        images = [
            (driver_info.fw_name, driver_info.config_name, driver_info.config_needed)
            for driver_info in rtk.Driver.DRIVER_INFOS
        ]

    for fw_name, config_name, config_needed in images:
        print(color("---", "yellow"))
        fw_image_out = output_dir / fw_name
        if not force and fw_image_out.exists():
            print(color(f"{fw_image_out} already exists, skipping", "red"))
            continue
        if config_name:
            config_image_out = output_dir / config_name
            if not force and config_image_out.exists():
                print(color("f{config_out} already exists, skipping", "red"))
                continue

        try:
            fw_image = download_file(base_url, fw_name, remove_suffix)
        except urllib.error.HTTPError as error:
            print(f"Failed to download {fw_name}: {error}")
            continue

        config_image = None
        if config_name:
            try:
                config_image = download_file(base_url, config_name, remove_suffix)
            except urllib.error.HTTPError as error:
                if config_needed:
                    print(f"Failed to download {config_name}: {error}")
                    continue
                else:
                    print(f"No config available as {config_name}")

        fw_image_out.write_bytes(fw_image)
        if parse and config_name:
            print(color("Parsing:", "cyan"), fw_name)
            rtk_util.do_parse(fw_image_out)
        if config_image:
            config_image_out.write_bytes(config_image)


# -----------------------------------------------------------------------------
if __name__ == '__main__':
    main()
