#!/usr/bin/env python
# Copyright 2015 gRPC authors.
#
# 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 print_function

import json
import os
import re
import sys

root = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '../../..'))
with open(
        os.path.join(root, 'tools', 'run_tests', 'generated',
                     'sources_and_headers.json')) as f:
    js = json.loads(f.read())

re_inc1 = re.compile(r'^#\s*include\s*"([^"]*)"')
assert re_inc1.match('#include "foo"').group(1) == 'foo'
re_inc2 = re.compile(r'^#\s*include\s*<((grpc|grpc\+\+)/[^"]*)>')
assert re_inc2.match('#include <grpc++/foo>').group(1) == 'grpc++/foo'


def get_target(name):
    for target in js:
        if target['name'] == name:
            return target
    assert False, 'no target %s' % name


def get_headers_transitive():
    """Computes set of headers transitively provided by each target"""
    target_headers_transitive = {}
    for target in js:
        target_name = target['name']
        assert not target_headers_transitive.has_key(target_name)
        target_headers_transitive[target_name] = set(target['headers'])

    # Make sure each target's transitive headers contain those
    # of their dependencies. If not, add them and continue doing
    # so until we get a full pass over all targets without any updates.
    closure_changed = True
    while closure_changed:
        closure_changed = False
        for target in js:
            target_name = target['name']
            for dep in target['deps']:
                headers = target_headers_transitive[target_name]
                old_count = len(headers)
                headers.update(target_headers_transitive[dep])
                if old_count != len(headers):
                    closure_changed = True
    return target_headers_transitive


# precompute transitive closure of headers provided by each target
target_headers_transitive = get_headers_transitive()


def target_has_header(target, name):
    if name in target_headers_transitive[target['name']]:
        return True
    if name.startswith('absl/'):
        return True
    if name in [
            'src/core/lib/profiling/stap_probes.h',
            'src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.h'
    ]:
        return True
    return False


def produces_object(name):
    return os.path.splitext(name)[1] in ['.c', '.cc']


c_ish = {}
obj_producer_to_source = {'c': c_ish, 'c++': c_ish, 'csharp': {}}

errors = 0
for target in js:
    if not target['third_party']:
        for fn in target['src']:
            with open(os.path.join(root, fn)) as f:
                src = f.read().splitlines()
            for line in src:
                m = re_inc1.match(line)
                if m:
                    if not target_has_header(target, m.group(1)):
                        print(
                            'target %s (%s) does not name header %s as a dependency'
                            % (target['name'], fn, m.group(1)))
                        errors += 1
                m = re_inc2.match(line)
                if m:
                    if not target_has_header(target, 'include/' + m.group(1)):
                        print(
                            'target %s (%s) does not name header %s as a dependency'
                            % (target['name'], fn, m.group(1)))
                        errors += 1
    if target['type'] in ['lib', 'filegroup']:
        for fn in target['src']:
            language = target['language']
            if produces_object(fn):
                obj_base = os.path.splitext(os.path.basename(fn))[0]
                if obj_base in obj_producer_to_source[language]:
                    if obj_producer_to_source[language][obj_base] != fn:
                        print(
                            'target %s (%s) produces an aliased object file with %s'
                            % (target['name'], fn,
                               obj_producer_to_source[language][obj_base]))
                else:
                    obj_producer_to_source[language][obj_base] = fn

assert errors == 0
