# Copyright 2018 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""The Build API entry point."""

import logging
import os

from chromite.api import api_config as api_config_lib
from chromite.api import controller
from chromite.api import message_util
from chromite.api import router as router_lib
from chromite.api.gen.chromite.api import build_api_config_pb2
from chromite.lib import commandline
from chromite.lib import cros_build_lib
from chromite.utils import matching


def GetParser():
  """Build the argument parser."""
  parser = commandline.ArgumentParser(description=__doc__)

  parser.add_argument(
      'service_method',
      help='The "chromite.api.Service/Method" that is being called.')
  # Input arguments.
  input_args = parser.add_mutually_exclusive_group(required=True)
  input_args.add_argument(
      '--input-binary',
      type='path',
      help='Path to the protobuf binary serialization of the input message.')
  input_args.add_argument(
      '--input-json',
      type='path',
      help='Path to the JSON serialized input argument protobuf message.')
  # Output options.
  parser.add_argument(
      '--output-binary',
      type='path',
      help='The path to which the protobuf binary serialization of the '
           'response message should be written.')
  parser.add_argument(
      '--output-json',
      type='path',
      help='The path to which the JSON serialization of the response message '
           'should be written.')
  # Config options.
  config_args = parser.add_mutually_exclusive_group()
  config_args.add_argument(
      '--config-binary',
      type='path',
      help='The path to the protobuf binary serialization of the Build API '
           'call configs.')
  config_args.add_argument(
      '--config-json',
      type='path',
      help='The path to the JSON encoded Build API call configs.')

  return parser


def _ParseArgs(argv, router):
  """Parse and validate arguments."""
  parser = GetParser()
  opts, unknown = parser.parse_known_args(
      argv, namespace=commandline.ArgumentNamespace())
  parser.DoPostParseSetup(opts, unknown)

  if unknown:
    logging.warning('Unknown args ignored: %s', ' '.join(unknown))

  methods = router.ListMethods()

  # Positional service_method argument validation.
  parts = opts.service_method.split('/')
  if len(parts) != 2:
    parser.error('Invalid service/method specification format. It should be '
                 'something like chromite.api.SdkService/Create.')

  if opts.service_method not in methods:
    # Unknown method, try to match against known methods and make a suggestion.
    # This is just for developer sanity, e.g. misspellings when testing.
    matched = matching.GetMostLikelyMatchedObject(
        methods, opts.service_method, matched_score_threshold=0.6)
    error = 'Unrecognized service name.'
    if matched:
      error += '\nDid you mean: \n%s' % '\n'.join(matched)
    parser.error(error)

  opts.service = parts[0]
  opts.method = parts[1]

  # Input and output validation.
  if not opts.output_binary and not opts.output_json:
    parser.error('At least one output file must be specified.')

  if not os.path.exists(opts.input_binary or opts.input_json):
    parser.error('Input file does not exist.')

  config_msg = build_api_config_pb2.BuildApiConfig()
  if opts.config_json:
    handler = message_util.get_message_handler(opts.config_json,
                                               message_util.FORMAT_JSON)
  else:
    handler = message_util.get_message_handler(opts.config_binary,
                                               message_util.FORMAT_BINARY)

  if opts.config_json or opts.config_binary:
    # We have been given a config, so read it.
    try:
      handler.read_into(config_msg)
    except message_util.Error as e:
      parser.error(str(e))

  opts.config = api_config_lib.build_config_from_proto(config_msg)
  opts.config_handler = handler

  opts.Freeze()
  return opts


def _get_io_handlers(opts):
  """Build the input and output handlers."""
  if opts.input_binary:
    input_handler = message_util.get_message_handler(opts.input_binary,
                                                     message_util.FORMAT_BINARY)
  else:
    input_handler = message_util.get_message_handler(opts.input_json,
                                                     message_util.FORMAT_JSON)

  output_handlers = []
  if opts.output_binary:
    handler = message_util.get_message_handler(opts.output_binary,
                                               message_util.FORMAT_BINARY)
    output_handlers.append(handler)
  if opts.output_json:
    handler = message_util.get_message_handler(opts.output_json,
                                               message_util.FORMAT_JSON)
    output_handlers.append(handler)

  return input_handler, output_handlers


def main(argv):
  router = router_lib.GetRouter()
  opts = _ParseArgs(argv, router)

  if opts.config.log_path:
    logging.warning('Ignoring log_path config option')
  if 'BUILD_API_TEE_LOG_FILE' in os.environ:
    logging.warning('Ignoring $BUILD_API_TEE_LOG_FILE env var')

  if opts.config.mock_invalid:
    # --mock-invalid handling. We print error messages, but no output is ever
    # set for validation errors, so we can handle it by just giving back the
    # correct return code here.
    return controller.RETURN_CODE_INVALID_INPUT

  input_handler, output_handlers = _get_io_handlers(opts)

  try:
    return router.Route(opts.service, opts.method, opts.config, input_handler,
                        output_handlers, opts.config_handler)
  except router_lib.Error as e:
    # Handle router_lib.Error derivatives nicely, but let anything else bubble
    # up.
    cros_build_lib.Die(e)
