#!/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/track_event/track_event.proto',
      'src/trace_processor/importers/proto/track_event.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())
