#!/usr/bin/env python3

# Copyright 2025 Google LLC
#
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import argparse
import difflib
import os
import shutil
import subprocess
import sys
import tempfile

# Third party dependencies necessary for Dawn to generate its version of the header.
THIRD_PARTY_DIR = os.path.join('third_party')
JINJA2_DIR = os.path.join('third_party', 'jinja2')
MARKUPSAFE_DIR = os.path.join('third_party', 'markupsafe')

# Dawn generator constants.
DAWN_GENERATOR = os.path.join('generator', 'dawn_json_generator.py')
DAWN_GENERATOR_TEMPLATE_DIR = os.path.join('generator', 'templates')
DAWN_JSON = os.path.join('src', 'dawn', 'dawn.json')
DAWN_WEBGPU_HEADER_TARGET = 'webgpu_headers'

# Upstream webgpu-header constants.
WEBGPU_HEADER = os.path.join('third_party', 'webgpu-headers', 'src',
                             'webgpu.h')

# Default output file locations.
DAWN_GENERATED_HEADER = os.path.join('webgpu-headers', 'webgpu.h')
WEBGPU_GENERATED_HEADER = os.path.join('webgpu-headers', 'webgpu_upstream.h')
GENERATED_DIFF = os.path.join('webgpu-headers', 'webgpu.h.diff')


# Helper that removes all comments from headers so that they can be diff-ed easier.
def _remove_comments(input_path, output_path):
    lines = []
    with open(input_path, 'r') as input:
        last_line_was_comment = False
        in_comment_block = False
        for line in input:
            stripped = line.strip()

            # If we are in a comment block, skip until we find the end.
            if in_comment_block:
                if stripped.endswith("*/"):
                    in_comment_block = False
                    last_line_was_comment = True
                continue

            # Drop empty lines directly following comments.
            if not stripped and last_line_was_comment:
                continue

            if stripped.startswith('//'):
                # Simple single line comment case, just skip the line.
                last_line_was_comment = True
                continue

            if stripped.startswith("/*") and stripped.endswith("*/"):
                # Simple single line comment with multi-line syntax, just skip the line.
                last_line_was_comment = True
                continue

            if stripped.startswith("/*") and "*/" not in stripped:
                # Otherwise, if we are a multi-line comment that isn't inlined.
                in_comment_block = True
                continue

            last_line_was_comment = False
            lines.append(line)

    with open(output_path, 'w') as output:
        for line in lines:
            output.write(line)


# Helper that just calls into Dawn's generators and generates webgpu.h without
# comments.
def _gen_dawn_header(dir):
    subprocess.check_call([
        sys.executable, DAWN_GENERATOR, '--template-dir',
        DAWN_GENERATOR_TEMPLATE_DIR, '--output-dir', dir, '--dawn-json',
        DAWN_JSON, '--targets', DAWN_WEBGPU_HEADER_TARGET, '--jinja2-path',
        JINJA2_DIR, '--markupsafe-path', MARKUPSAFE_DIR
    ])
    _remove_comments(os.path.join(dir, DAWN_GENERATED_HEADER),
                     os.path.join(dir, DAWN_GENERATED_HEADER))


# Helper that removes comments from the upstream webgpu.h file.
def _gen_webgpu_header(dir):
    _remove_comments(WEBGPU_HEADER, os.path.join(dir, WEBGPU_GENERATED_HEADER))


# Helper that generates the diff between the Dawn and upstream headers.
def _gen_header_diff(temp_dir, output_dir):
    _gen_dawn_header(temp_dir)
    _gen_webgpu_header(temp_dir)

    with open(os.path.join(temp_dir, DAWN_GENERATED_HEADER), 'r') as dawn_header, \
         open(os.path.join(temp_dir, WEBGPU_GENERATED_HEADER), 'r') as webgpu_header, \
         open(os.path.join(output_dir, GENERATED_DIFF), 'w') as diff_file:
        diff = difflib.unified_diff(webgpu_header.readlines(),
                                    dawn_header.readlines(),
                                    fromfile='webgpu_header',
                                    tofile='dawn_header')
        # Skip writing all the line numbers as these all change every time
        # anything in the file changes.
        for line in diff:
            if line.startswith('@@'):
                diff_file.writelines('@@\n')
            else:
                diff_file.writelines(line)


# Helper that verifies that all the necessary dependencies to run checks are
# available. If they are not, we just silently pass for now.
def _check_deps():
    if not os.path.isdir(JINJA2_DIR):
        print(
            f'Third party dependency jinja2 is not available at {JINJA2_DIR}')
        return False
    if not os.path.isdir(MARKUPSAFE_DIR):
        print(
            f'Third party dependency markupsafe is not available at {MARKUPSAFE_DIR}'
        )
        return False
    if not os.path.exists(WEBGPU_HEADER):
        print(
            f'Third party upstream webgpu.h is not available at {WEBGPU_HEADER}'
        )
        return False
    return True


def main(args):
    parser = argparse.ArgumentParser()
    parser.add_argument('action', choices=('gen', 'check'))
    options = parser.parse_args()

    if options.action == 'gen':
        with tempfile.TemporaryDirectory() as temp_dir:
            _gen_header_diff(temp_dir, THIRD_PARTY_DIR)
        return 0

    if options.action == 'check':
        if not _check_deps():
            return 0
        with tempfile.TemporaryDirectory() as temp_dir:
            _gen_header_diff(temp_dir, temp_dir)

            with open(os.path.join(temp_dir, GENERATED_DIFF), 'r') as temp_file, \
                 open(os.path.join(THIRD_PARTY_DIR, GENERATED_DIFF), 'r') as curr_file:
                diff = ''.join(
                    difflib.unified_diff(temp_file.readlines(),
                                         curr_file.readlines()))
                if diff:
                    print(
                        "Changes resulted in new diffs between Dawn's and the "
                        "upstream webgpu.h. Please re-run "
                        "'third_party/webgpu-headers/cli gen' manually and "
                        "verify/commit the new diffs in "
                        "'third_party/webgpu-headers/webgpu.h.diff' if the "
                        "changes are expected.")
                    return 1

        return 0


if __name__ == '__main__':
    sys.exit(main(sys.argv))
