#!/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
from compat import iteritems

SOURCE_TARGET = [
    (
      'protos/perfetto/config/perfetto_config.proto',
      'src/perfetto_cmd/perfetto_config.descriptor.h',
    ),
    (
      'src/protozero/test/example_proto/test_messages.proto',
      'src/protozero/test/example_proto/test_messages.descriptor.h'
    ),
    (
      'protos/perfetto/trace_processor/trace_processor.proto',
      'src/trace_processor/python/perfetto/trace_processor/trace_processor.descriptor'
    ),
    (
      'protos/perfetto/metrics/metrics.proto',
      'src/trace_processor/python/perfetto/trace_processor/metrics.descriptor'
    ),
]

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), 'rb') as f:
    hash.update(f.read())
  return hash.hexdigest()


def find_protoc():
  for root, _, files in os.walk(os.path.join(ROOT_DIR, 'out')):
    if 'protoc' in files:
      return os.path.join(root, 'protoc')
  return None


def check_using_shas(source, target, file_with_shas):
  with open(file_with_shas, 'rb') as f:
    s = f.read()

  hashes = re.findall(r'// SHA1\((.*)\)\n// (.*)\n', s.decode())
  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 check_raw_descriptor(source, target):
  sha1_file = target + '.sha1'
  assert os.path.exists(sha1_file), \
      'SHA1 file {} does not exist and so cannot be checked'.format(sha1_file)

  check_using_shas(source, target, sha1_file)


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)

  if target.endswith('.descriptor.h'):
    check_using_shas(source, target, target)
  elif target.endswith('.descriptor'):
    check_raw_descriptor(source, target)


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

  proto_name = source_name[:-len('.proto')].title().replace("_", "")
  try:
    ord(descriptor_bytes[0])
    ordinal = ord
  except TypeError:
    ordinal = lambda x: x
  binary = '{' + ', '.join('{0:#04x}'
    .format(ordinal(c)) for c in descriptor_bytes) + '}'
  binary = textwrap.fill(
      binary, width=80, initial_indent='    ', subsequent_indent='     ')

  with open(os.path.join(ROOT_DIR, target), 'wb') as f:
    f.write("""/*
 * Copyright (C) 2019 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.
 */

#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}> k{proto_name}Descriptor{{
{binary}}};

}}  // namespace perfetto

#endif  // {include_guard}
""".format(
        proto_name=proto_name,
        size=len(descriptor_bytes),
        binary=binary,
        include_guard=target.replace('/', '_').replace('.', '_').upper() + '_',
        script_path=SCRIPT_PATH,
        script_hash=hash_path(__file__),
        source_path=source,
        source_hash=hash_path(os.path.join(source)),
    ).encode())


def write_raw_descriptor(source, target, descriptor_bytes):
  with open(target, 'wb') as out:
    out.write(descriptor_bytes)

  sha1_path = target + '.sha1'
  with open(sha1_path, 'wb') as c:
    c.write("""
// SHA1({script_path})
// {script_hash}
// SHA1({source_path})
// {source_hash}
""".format(
        script_path=SCRIPT_PATH,
        script_hash=hash_path(__file__),
        source_path=source,
        source_hash=hash_path(os.path.join(source)),
    ).encode())



def generate(source, target, protoc_path):
  with tempfile.NamedTemporaryFile() as fdescriptor:
    subprocess.check_call([
        protoc_path,
        '--include_imports',
        '--proto_path=.',
        '--proto_path=' + \
            os.path.join(ROOT_DIR, "buildtools", "protobuf", "src"),
        '--descriptor_set_out={}'.format(fdescriptor.name),
        source,
    ],
                          cwd=ROOT_DIR)

    s = fdescriptor.read()
    if target.endswith('.descriptor.h'):
      write_cpp_header(source, target, s)
    elif target.endswith('.descriptor'):
      write_raw_descriptor(source, target, s)
    else:
      raise Exception('Unsupported target extension for file {}'.format(target))

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:
      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())
