#!/usr/bin/env python
# Copyright (C) 2018 The Android Open Source Project
#
# 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
#
#      http://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.

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import os
import re
import sys
import argparse
import tempfile
import subprocess
import hashlib
import textwrap

SOURCE_TARGET = {
    'protos/perfetto/config/perfetto_config.proto':
            'src/perfetto_cmd/perfetto_config.descriptor.h',
}

ROOT_DIR = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))

SCRIPT_PATH = 'tools/gen_binary_descriptors'


def hash_path(path):
  hash = hashlib.sha1()
  with open(os.path.join(ROOT_DIR, path)) as f:
    hash.update(f.read())
  return hash.hexdigest()


def find_protoc():
  for root, dirs, files in os.walk(ROOT_DIR):
    if 'protoc' in files:
      return os.path.join(root, 'protoc')
    for name in ('src', 'buildtools'):
      if name in dirs:
        dirs.remove(name)
  return None


def check(source, target):
  assert os.path.exists(os.path.join(ROOT_DIR, target)), \
      'Output file {} does not exist and so cannot be checked'.format(target)

  with open(target, 'rb') as f:
    s = f.read()

  hashes = re.findall(r'// SHA1\((.*)\)\n// (.*)\n', s)
  assert sorted([SCRIPT_PATH, source]) == sorted([key for key, _ in hashes])
  for path, expected_sha1 in hashes:
    actual_sha1 = hash_path(os.path.join(ROOT_DIR, path))
    assert actual_sha1 == expected_sha1, \
        'In {} hash given for {} did not match'.format(target, path)


def generate(source, target, protoc_path):
  _, source_name = os.path.split(source)
  _, target_name = os.path.split(target)
  assert source_name.replace('.proto', '.descriptor.h') == target_name

  with tempfile.NamedTemporaryFile() as fdescriptor:
    subprocess.check_call([
        protoc_path,
        '--proto_path=protos',
        '-o{}'.format(fdescriptor.name),
        source,
    ], cwd=ROOT_DIR)

    s = fdescriptor.read()
    proto_name = source_name[:-len('.proto')].title().replace("_", "")
    constant_name = 'k' + proto_name + 'Descriptor'
    binary = '{' + ', '.join('{0:#04x}'.format(ord(c)) for c in s) + '}'
    binary = textwrap.fill(binary,
        width=80,
        initial_indent='    ',
        subsequent_indent='     ')
    include_guard = target.replace('/', '_').replace('.', '_').upper() + '_'

    with open(os.path.join(ROOT_DIR, target), 'wb') as f:
      f.write("""
#ifndef {include_guard}
#define {include_guard}

#include <stddef.h>
#include <stdint.h>

#include <array>

// This file was autogenerated by tools/gen_binary_descriptors. Do not edit.

// SHA1({script_path})
// {script_hash}
// SHA1({source_path})
// {source_hash}

// This is the proto {proto_name} encoded as a ProtoFileDescriptor to allow
// for reflection without libprotobuf full/non-lite protos.

namespace perfetto {{

constexpr std::array<uint8_t, {size}> {constant_name}{{
{binary}}};

}}  // namespace perfetto

#endif  // {include_guard}
""".format(**{
        'proto_name': proto_name,
        'size': len(s),
        'constant_name': constant_name,
        'binary': binary,
        'include_guard': include_guard,
        'script_path': SCRIPT_PATH,
        'script_hash': hash_path(__file__),
        'source_path': source,
        'source_hash': hash_path(os.path.join(source)),
      }))


def main():
  parser = argparse.ArgumentParser()
  parser.add_argument('--check-only', action='store_true')
  parser.add_argument('--protoc')
  args = parser.parse_args()

  try:
    for source, target in SOURCE_TARGET.iteritems():
      if args.check_only:
          check(source, target)
      else:
        protoc = args.protoc or find_protoc()
        assert protoc, 'protoc not found specific (--protoc PROTOC_PATH)'
        assert os.path.exists(protoc), '{} does not exist'.format(protoc)
        if protoc is not args.protoc:
          print('Using protoc: {}'.format(protoc))
        generate(source, target, protoc)
  except AssertionError as e:
    if not str(e):
      raise
    print('Error: {}'.format(e))
    return 1

if __name__ == '__main__':
  exit(main())
