#!/usr/bin/env python3

# Copyright 2020 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""This script is used to run the error_calculator binary.

  ./error_calculator.py 1 657579885 14 1

This script assumes it is being run from a third_party embedding in a fuchsia
checkout. If you are running from the cobalt standalone repository, run
'cobaltb.py calculate_error' instead. If the build configuration doesn't match
the assumed fuchsia or cobalt checkout, use the --bin_dir flag to specify the
path to the error_calculator and config_parser binaries.

A new version of the registry is generated every time.
"""

import subprocess
import os
import argparse
import sys

THIS_DIR = os.path.abspath(os.path.dirname(__file__))
COBALT_ROOT_DIR = os.path.abspath(os.path.join(THIS_DIR, '..'))
PRIVACY_PARAMS = os.path.join(COBALT_ROOT_DIR, 'src', 'algorithms', 'privacy',
                              'data', 'privacy_encoding_params')
REGISTRY_PROTO_DEFAULT = os.path.join(COBALT_ROOT_DIR, 'out', 'registry.pb')
POPULATION_DEFAULT = 100000


def estimate_from_args(error_binary, args):
  """Unpacks and validates command line arguments before calling error calculator.

  Args:
    error_binary: The filepath of the error calculator binary.
    args: Python arguments defined below.
  """
  _validate_args(args)
  estimate(error_binary, args.registry_proto, args.customer_id, args.project_id,
           args.metric_id, args.report_id, args.population, args.epsilon,
           args.min_denominator, args.min_value, args.max_value, args.max_count,
           args.simple)


def estimate(error_binary,
             registry_proto,
             customer_id,
             project_id,
             metric_id,
             report_id,
             population,
             epsilon=None,
             min_denominator=None,
             min_value=None,
             max_value=None,
             max_count=None,
             simple=False):
  """Calls the error_calculator binary with the specified arguments.

  Args:
    error_binary: The string filepath to the error calculator binary.
    registry_proto: The string filepath to the registry formatted as a
      serialized proto.
    customer_id: The integer customer id.
    project_id: The integer project id.
    metric_id: The integer metric id.
    report_id: The integer report id.
    population: Integer value estimating the number of reporting devices.
    epsilon: Optional; Epsilon value for which to estimate error.
    min_denominator: Optional; estimated minimum number of unique contributing
      devices per day.
    min_value: Optional; override the report's min_value.
    max_value: Optional; override the report's max_value.
    max_count: Optional; override the report's max_count.
    simple: Outputs a single estimate.
  """
  error_args = [
      '-registry_proto', registry_proto, '--privacy_params', PRIVACY_PARAMS,
      '--population',
      str(population)
  ]
  if epsilon:
    error_args = error_args + ['--epsilon', str(epsilon)]
  if min_denominator:
    error_args = error_args + ['--min_denominator', str(min_denominator)]
  if simple:
    error_args = error_args + ['--simple']
  if min_value:
    error_args = error_args + ['--min_value', str(min_value)]
  if max_value:
    error_args = error_args + ['--max_value', str(max_value)]
  if max_count:
    error_args = error_args + ['--max_count', str(max_count)]
  error_args = error_args + [
      str(customer_id),
      str(project_id),
      str(metric_id),
      str(report_id)
  ]
  subprocess.check_call([error_binary] + error_args)


# TODO(fxbug.dev/87101): Use the build system to generate the registry only when
# necessary.
def generate_registry(registry_proto, config_dir, config_parser):
  """Generates a binary encoding of the cobalt registry.

  Args:
    registry_proto: The filepath of the error calculator binary. This is the
      output of the config_parser and the input for the error_calculator
    config_dir: Location of the cobalt config.
    config_parser: Location of the binary used to generate the registry_proto.
  """
  if not config_parser:
    sys.exit('Run \'config_parser --out_filename %s\' and try again.' %
             registry_proto)
  subprocess.check_call([
      config_parser, '--output_file', registry_proto, '--config_dir',
      config_dir, '--privacy_encoding_params_file', PRIVACY_PARAMS
  ])
  print('Wrote binary encoding of registry to %s.\n' % registry_proto)


def add_parse_args(parser):
  """Adds the standard arguments required for the error_calculator.

  This is used to set arguments for this script and the cobaltb.py script.

  Args:
    parser: An ArgumentParser to be augmented with error calculator arguments.
  """
  parser.add_argument(
      '--registry_proto',
      help='Set a specific filepath for the binary encoding of the Cobalt Registry. Default: %s'
      % REGISTRY_PROTO_DEFAULT,
      default=REGISTRY_PROTO_DEFAULT)
  parser.add_argument(
      '--population',
      help='Expected number of devices contributing to the report. Default: %s'
      % POPULATION_DEFAULT,
      default=POPULATION_DEFAULT)
  parser.add_argument(
      '--bin_dir',
      help='Directory containing the error_calculator and config_parser binaries. '
      'If unset, the script attempts to find binaries based on the default '
      'build configuration for Fuchsia and Cobalt.',
      default=None)
  parser.add_argument(
      '--epsilon',
      help='If set, estimates the error using the specified epsilon value.')
  parser.add_argument(
      '--min_denominator',
      help='Estimated minimum number of unique contributing devices per day.')
  parser.add_argument(
      '--min_value', help='Optionally overrides the report\'s MinValue field.')
  parser.add_argument(
      '--max_value', help='Optionally overrides the report\'s MaxValue field.')
  parser.add_argument(
      '--max_count', help='Optionally overrides the report\'s MaxCount field.')
  parser.add_argument(
      '--simple',
      default=False,
      action='store_true',
      help='Output a single error estimate.')
  parser.add_argument(
      'customer_id', help='a report\'s parent customer id', type=int)
  parser.add_argument(
      'project_id', help='a report\'s parent project id.', type=int)
  parser.add_argument(
      'metric_id', help='a report\'s parent metric id.', type=int)
  parser.add_argument(
      'report_id', help='a report\'s parent report id.', type=int)


def _validate_args(args):
  if args.registry_proto == None:
    sys.exit('--registry_proto is required')
  if args.population == None:
    sys.exit('--population flag is required')
  if not os.path.exists(args.registry_proto):
    sys.exit(
        'No serialized proto found. Try running \'config_parser --out_filename %s\' and try again.'
        % args.registry_proto)


if __name__ == '__main__':
  # Assumes the user is running from a Fuchsia checkout.
  # If you're running this script directly from a cobalt checkout, use
  # `cobaltb.py calculate_error` instead.
  parser = argparse.ArgumentParser()
  add_parse_args(parser)
  args = parser.parse_args()

  if args.bin_dir:
    bin_dir = args.bin_dir
  else:
    out = subprocess.check_output(['fx', 'get-build-dir'])
    out_dir = out.decode('utf-8').rstrip()
    bin_dir = os.path.join(out_dir, 'host_x64')

  error_binary = os.path.join(bin_dir, 'error_calculator')
  config_parser = os.path.join(bin_dir, 'config_parser')
  config_dir = os.path.join(COBALT_ROOT_DIR, '..', 'cobalt_config')
  config_dir = os.path.abspath(config_dir)
  if not os.path.exists(error_binary):
    sys.exit(
        'Error Calculator binary not found: %s.\nRun \'fx build\' and try again.'
        % error_binary)

  generate_registry(args.registry_proto, config_dir, config_parser)
  estimate_from_args(error_binary, args)
