#!/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',
    'protos/perfetto/metrics/metrics.proto':
            'src/trace_processor/metrics/metrics.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,
        '--include_imports',
        '--proto_path=protos',
        '--descriptor_set_out={}'.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())
