#!/usr/bin/env python3
#
# Copyright 2021 The Cobalt Authors. All Rights Reserved.
#
# 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.
"""Formats ninja compilation databases to be easily diffed against each other.

Primarily used for looking at the differences between GYP and GN builds during
the GN migration.

To test, first generate a the ninja build files, then use

ninja -t compdb > out.json

in the build directory to generate a JSON file containing all actions ninja
would run. The run this script on that file and diff it with another.
"""

import argparse
import json
import os

from typing import List, Tuple

_ACTION_COMPONENTS = ['directory', 'command', 'file', 'output']
STRIP = 0


def make_path_absolute(path: str, directory: str) -> str:
  if os.path.isabs(path):
    return path

  return os.path.normpath(os.path.join(directory, path))


def remove_directory_path(path: str, directory: str) -> str:
  if STRIP :
    dirsplit = directory.split(os.path.sep)
    directory = os.path.sep.join(dirsplit[:-(STRIP)])
  if os.path.commonpath([path, directory]) != directory:
    return path

  return os.path.relpath(path, directory)


def normalize_if_pathlike(path: str, directory: str) -> str:
  absolute_path = make_path_absolute(path, directory)
  if os.path.exists(absolute_path):
    return remove_directory_path(absolute_path, directory)
  return path


def relativize_path(path: str, directory: str) -> str:
  path = make_path_absolute(path, directory)
  return remove_directory_path(path, directory)


def validate_json_database(json_content: object):
  for entry in json_content:
    for component in _ACTION_COMPONENTS:
      if component not in entry:
        raise ValueError(f'Ninja json entry is missing {component} field.')


def normalize_command(command: str, directory: str) -> Tuple[List[str], object]:
  command_list = command.split()
  command_with_normalized_paths = [
      normalize_if_pathlike(e, directory) for e in command_list
  ]

  # command_parser = argparse.ArgumentParser()
  # command_parser.add_argument('-x', type=str)
  # command_parser.add_argument('-MF', type=str)
  # command_parser.add_argument('-o', type=str)
  # command_parser.add_argument('-c', type=str)
  # parsed, unknown = command_parser.parse_known_args(
  #     command_with_normalized_paths)
  # return (parsed, sorted(unknown, reverse=True))
  return sorted(command_with_normalized_paths, reverse=True)


def normalize_all_paths(json_content: List[object]) -> List[object]:
  for entry in json_content:
    directory = entry['directory']
    command = normalize_command(entry['command'], directory)
    file_entry = relativize_path(entry['file'], directory)
    output_entry = entry['output']
    yield {'command': command, 'file': file_entry, 'output': output_entry}


def normalize_json_file(filename: str) -> List[object]:
  with open(filename) as f:
    content = json.load(f)

  validate_json_database(content)
  normalized_content = normalize_all_paths(content)
  return sorted(normalized_content, key=lambda x: x['output'])


def main(json_database: str, output_filename: str):
  json_content = normalize_json_file(json_database)
  with open(output_filename, 'w') as f:
    json.dump(json_content, f, indent=4, sort_keys=True)


if __name__ == '__main__':
  parser = argparse.ArgumentParser()
  parser.add_argument('json_filename', type=str)
  parser.add_argument('-o', '--output', type=str)
  parser.add_argument('-p', '--strip', type=int)
  args = parser.parse_args()
  if args.strip:
    STRIP = int(args.strip)
  output = args.output if args.output else 'normalized_' + os.path.basename(
      args.json_filename)
  main(args.json_filename, output)
