#!/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 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 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):
    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())
