#!/usr/bin/env python3
# Copyright 2022 The Dawn & Tint Authors
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this
#    list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
#    this list of conditions and the following disclaimer in the documentation
#    and/or other materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its
#    contributors may be used to endorse or promote products derived from
#    this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import os, subprocess, sys, shutil

from generator_lib import Generator, run_generator, FileRender, GeneratorOutput


def get_git():
    # Will find git, git.exe, git.bat...
    git_exec = shutil.which("git")
    if not git_exec:
        raise Exception("No git executable found")

    return git_exec


def get_git_hash(dawn_dir):
    try:
        result = subprocess.run([get_git(), "rev-parse", "HEAD"],
                                stdout=subprocess.PIPE,
                                cwd=dawn_dir)
        if result.returncode == 0:
            return result.stdout.decode("utf-8").strip()
    except Exception:
        return ""
    # No hash was available (possibly) because the directory was not a git checkout. Dawn should
    # explicitly handle its absenece and disable features relying on the hash, i.e. caching.
    return ""


def get_git_head(dawn_dir):
    return os.path.join(dawn_dir, ".git", "HEAD")


def git_exists(dawn_dir):
    return os.path.exists(get_git_head(dawn_dir))


def unpack_git_ref(packed, resolved):
    with open(packed) as fin:
        refs = fin.read().strip().split("\n")

    # Strip comments
    refs = [ref.split(" ") for ref in refs if ref.strip()[0] != "#"]

    # Parse results which are in the format [<gitHash>, <refFile>] from previous step.
    refs = [gitHash for (gitHash, refFile) in refs if refFile == resolved]
    if len(refs) == 1:
        with open(resolved, "w") as fout:
            fout.write(refs[0] + "\n")
        return True
    return False


def get_git_resolved_head(dawn_dir):
    result = subprocess.run(
        [get_git(), "rev-parse", "--symbolic-full-name", "HEAD"],
        stdout=subprocess.PIPE,
        cwd=dawn_dir)
    if result.returncode != 0:
        raise Exception("Failed to execute git rev-parse to resolve git head:",
                        result.stdout)

    resolved = os.path.join(dawn_dir, ".git",
                            result.stdout.decode("utf-8").strip())

    # Check a packed-refs file exists. If so, we need to potentially unpack and include it as a dep.
    packed = os.path.join(dawn_dir, ".git", "packed-refs")
    if os.path.exists(packed) and unpack_git_ref(packed, resolved):
        return [packed, resolved]

    if not os.path.exists(resolved):
        raise Exception("Unable to resolve git HEAD hash file:", resolved)
    return [resolved]


def get_version(args):
    version_file = args.version_file
    if version_file:
        with open(version_file) as f:
            return f.read()
    return get_git_hash(os.path.abspath(args.dawn_dir))


def get_version_byte_array(version_str):
    version_str = version_str.strip()
    if not version_str:
        # If the version string is empty, generate an array of 20 zero bytes.
        return ", ".join(["0x00"] * 20)
    assert len(
        version_str
    ) == 40, "Version string must be a 40-character git hash if not empty."
    byte_values = [
        f"0x{version_str[i:i+2]}" for i in range(0, len(version_str), 2)
    ]
    return ", ".join(byte_values)


def compute_params(args):
    version = get_version(args)
    return {
        "get_version_byte_array": lambda: get_version_byte_array(version),
    }


class DawnVersionGenerator(Generator):

    def get_description(self):
        return (
            "Generates version dependent Dawn code. Currently regenerated dependent on the version "
            "header (if available), otherwise tries to use git hash.")

    def add_commandline_arguments(self, parser):
        parser.add_argument(
            "--dawn-dir",
            required=True,
            type=str,
            help="The Dawn root directory path to use",
        )
        parser.add_argument(
            "--version-file",
            required=False,
            type=str,
            help=
            ("Path to one-liner version string file used when git may not be present. "
             "In general the version string is a git hash."))

    def get_dependencies(self, args):
        dawn_dir = os.path.abspath(args.dawn_dir)
        version_file = args.version_file

        if version_file:
            return [version_file]
        if git_exists(dawn_dir):
            try:
                return [get_git_head(dawn_dir)
                        ] + get_git_resolved_head(dawn_dir)
            except Exception:
                return []
        return []

    def get_outputs(self, args):
        params = compute_params(args)

        renders = [
            FileRender("dawn/common/Version.h",
                       "src/dawn/common/Version_autogen.h", [params]),
        ]
        return GeneratorOutput(renders=renders, imported_templates=[])


if __name__ == "__main__":
    sys.exit(run_generator(DawnVersionGenerator()))
