#!/usr/bin/env python3
#
# Copyright 2013 The Flutter Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import argparse
import glob
import re
import os
import subprocess
import sys
from compatibility_helper import byte_str_decode

if 'STORAGE_BUCKET' not in os.environ:
  print('The GCP storage bucket must be provided as an environment variable.')
  sys.exit(1)
BUCKET = os.environ['STORAGE_BUCKET']

if 'GCP_PROJECT' not in os.environ:
  print('The GCP project must be provided as an environment variable.')
  sys.exit(1)
PROJECT = os.environ['GCP_PROJECT']

script_dir = os.path.dirname(os.path.realpath(__file__))
buildroot_dir = os.path.abspath(os.path.join(script_dir, '..', '..'))
out_dir = os.path.join(buildroot_dir, 'out')
error_re = re.compile(r'[EF]/flutter.+')


def run_firebase_test(apk, results_dir):
  # game-loop tests are meant for OpenGL apps.
  # This type of test will give the application a handle to a file, and
  # we'll write the timeline JSON to that file.
  # See https://firebase.google.com/docs/test-lab/android/game-loop
  # Pixel 5. As of this commit, this is a highly available device in FTL.
  process = subprocess.Popen(
      [
          'gcloud',
          '--project',
          PROJECT,
          'firebase',
          'test',
          'android',
          'run',
          '--type',
          'game-loop',
          '--app',
          apk,
          '--timeout',
          '2m',
          '--results-bucket',
          BUCKET,
          '--results-dir',
          results_dir,
          '--device',
          'model=oriole,version=33',
      ],
      stdout=subprocess.PIPE,
      stderr=subprocess.STDOUT,
      universal_newlines=True,
  )
  return process


def check_logcat(results_dir):
  logcat = subprocess.check_output([
      'gsutil', 'cat',
      '%s/%s/*/logcat' % (BUCKET, results_dir)
  ])
  logcat = byte_str_decode(logcat)
  if not logcat:
    sys.exit(1)

  logcat_matches = error_re.findall(logcat)
  if logcat_matches:
    print('Errors in logcat:')
    print(logcat_matches)
    sys.exit(1)


def check_timeline(results_dir):
  gsutil_du = subprocess.check_output([
      'gsutil', 'du',
      '%s/%s/*/game_loop_results/results_scenario_0.json' %
      (BUCKET, results_dir)
  ])
  gsutil_du = byte_str_decode(gsutil_du)
  gsutil_du = gsutil_du.strip()
  if gsutil_du == '0':
    print('Failed to produce a timeline.')
    sys.exit(1)


def main():
  parser = argparse.ArgumentParser()
  parser.add_argument(
      '--variant',
      dest='variant',
      action='store',
      default='android_profile_arm64',
      help='The engine variant to run tests for.'
  )
  parser.add_argument(
      '--build-id',
      default=os.environ.get('SWARMING_TASK_ID', 'local_test'),
      help='A unique build identifier for this test. Used to sort results in the GCS bucket.'
  )

  args = parser.parse_args()

  apks_dir = os.path.join(out_dir, args.variant, 'firebase_apks')
  apks = glob.glob('%s/*.apk' % apks_dir)

  if not apks:
    print('No APKs found at %s' % apks_dir)
    return 1

  git_revision = subprocess.check_output(['git', 'rev-parse', 'HEAD'],
                                         cwd=script_dir)
  git_revision = byte_str_decode(git_revision)
  git_revision = git_revision.strip()
  results = []
  apk = None
  for apk in apks:
    results_dir = '%s/%s/%s' % (
        os.path.basename(apk), git_revision, args.build_id
    )
    process = run_firebase_test(apk, results_dir)
    results.append((results_dir, process))

  for results_dir, process in results:
    for line in iter(process.stdout.readline, ''):
      print(line.strip())
    return_code = process.wait()
    if return_code != 0:
      print('Firebase test failed with code: %s' % return_code)
      sys.exit(return_code)

    print('Checking logcat for %s' % results_dir)
    check_logcat(results_dir)
    # scenario_app produces a timeline, but the android image test does not.
    if 'scenario' in apk:
      print('Checking timeline for %s' % results_dir)
      check_timeline(results_dir)

  return 0


if __name__ == '__main__':
  sys.exit(main())
