#!/usr/bin/python
#
# Protocol Buffers - Google's data interchange format
# Copyright 2023 Google LLC.  All rights reserved.
#
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file or at
# https://developers.google.com/open-source/licenses/bsd

"""A tool to convert MODULE.bazel -> CMakeLists.txt.

This tool is very protobuf-specific at the moment, and should not be seen as a
generic Bazel -> CMake converter.
"""

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import os
import re
import sys
import textwrap


class ExtensionFunctions(object):
  """A fake extension that we can use to get the functions we need."""

  def defaults(self, *args, **kwargs):
    pass

  def toolchain(self, *args, **kwargs):
    pass

  def parse(self, *args, **kwargs):
    pass

  def spec(self, *args, **kwargs):
    pass

  def from_specs(self, *args, **kwargs):
    pass

  def install(self, *args, **kwargs):
    pass

  def bundle_fetch(self, *args, **kwargs):
    pass

  def find(self, *args, **kwargs):
    pass

  def source_archive(self, *args, **kwargs):
    pass

  def nuget_package(self, *args, **kwargs):
    pass


def empty_func(*args, **kwargs):
  pass


class ModuleFileFunctions(object):
  """A fake MODULE file that we can exec() to get the functions we need."""

  def __init__(self, converter):
    self.converter = converter

  def module(self, *args, **kwargs):
    pass

  def bazel_dep(self, name, version, **kwargs):
    # Strip BCR-specific version suffixes (e.g. 1.17.0.bcr.2 -> 1.17.0)
    # since they don't correspond to upstream git tags.
    version = re.sub(r"\.bcr\.\d+", "", version)
    self.converter.toplevel += textwrap.dedent(
        """\
      set(%(name)s-version "%(version)s")
    """
        % {
            "name": name,
            "version": version,
        }
    )

  def register_toolchains(self, *args, **kwargs):
    pass

  def use_repo(self, *args, **kwargs):
    pass

  def use_repo_rule(self, *args, **kwargs):
    return empty_func

  def single_version_override(self, *args, **kwargs):
    pass

  def use_extension(self, *args, **kwargs):
    return ExtensionFunctions()

  def local_path_override(self, *args, **kwargs):
    pass

  def git_override(self, *args, **kwargs):
    pass

  def archive_override(self, *args, **kwargs):
    pass


class Converter(object):

  def __init__(self):
    self.toplevel = ""
    self.if_lua = ""

  def convert(self):
    return self.template % {
        "toplevel": converter.toplevel,
    }

  template = textwrap.dedent("""\
    # Auto-generated by @//cmake:make_dependencies
    #
    # This file contains lists of external dependencies based on our Bazel
    # config. It should be included from a hand-written CMake file that uses
    # them.
    #
    # Changes to this file will be overwritten based on Bazel definitions.

    if(${CMAKE_VERSION} VERSION_GREATER 3.16 OR ${CMAKE_VERSION} VERSION_EQUAL 3.16)
      include_guard()
    endif()

    %(toplevel)s

  """)


data = {}
converter = Converter()


def GetDict(obj):
  ret = {}
  for k in dir(obj):
    if not k.startswith("_"):
      ret[k] = getattr(obj, k)
  return ret


# We take the MODULE path as a command-line argument to ensure that we can find
# it regardless of how exactly Bazel was invoked.
exec(open(sys.argv[1]).read(), GetDict(ModuleFileFunctions(converter)))

with open(sys.argv[2], "w") as f:
  f.write(converter.convert())
