#!/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(jaredweinstein): 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)
