/*
 *  Copyright 2017 The WebRTC Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#import <UIKit/UIKit.h>

#include "test/ios/coverage_util_ios.h"
#include "test/ios/test_support.h"
#include "test/testsupport/perf_test.h"

#import "sdk/objc/helpers/NSString+StdString.h"

// Springboard will kill any iOS app that fails to check in after launch within
// a given time. Starting a UIApplication before invoking TestSuite::Run
// prevents this from happening.

// InitIOSRunHook saves the TestSuite and argc/argv, then invoking
// RunTestsFromIOSApp calls UIApplicationMain(), providing an application
// delegate class: WebRtcUnitTestDelegate. The delegate implements
// application:didFinishLaunchingWithOptions: to invoke the TestSuite's Run
// method.

// Since the executable isn't likely to be a real iOS UI, the delegate puts up a
// window displaying the app name. If a bunch of apps using MainHook are being
// run in a row, this provides an indication of which one is currently running.

static int (*g_test_suite)(void) = NULL;
static int g_argc;
static char **g_argv;
static bool g_write_perf_output;
static absl::optional<std::vector<std::string>> g_metrics_to_plot;

@interface UIApplication (Testing)
- (void)_terminateWithStatus:(int)status;
@end

@interface WebRtcUnitTestDelegate : NSObject {
  UIWindow *_window;
}
- (void)runTests;
@end

@implementation WebRtcUnitTestDelegate

- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  CGRect bounds = [[UIScreen mainScreen] bounds];

  _window = [[UIWindow alloc] initWithFrame:bounds];
  [_window setBackgroundColor:[UIColor whiteColor]];
  [_window makeKeyAndVisible];

  // Add a label with the app name.
  UILabel *label = [[UILabel alloc] initWithFrame:bounds];
  label.text = [[NSProcessInfo processInfo] processName];
  label.textAlignment = NSTextAlignmentCenter;
  [_window addSubview:label];

  // An NSInternalInconsistencyException is thrown if the app doesn't have a
  // root view controller. Set an empty one here.
  [_window setRootViewController:[[UIViewController alloc] init]];

  // Queue up the test run.
  [self performSelector:@selector(runTests) withObject:nil afterDelay:0.1];
  return YES;
}

- (void)runTests {
  rtc::test::ConfigureCoverageReportPath();

  int exitStatus = g_test_suite();

  if (g_write_perf_output) {
    // Stores data into a json file under the app's document directory.
    // TODO(https://crbug.com/1029452): Change ext to .pb when histograms are
    // the default.
    NSString* fileName = @"perf_result.json";
    NSArray<NSString*>* outputDirectories = NSSearchPathForDirectoriesInDomains(
        NSDocumentDirectory, NSUserDomainMask, YES);
    if ([outputDirectories count] != 0) {
      NSString* outputPath =
          [outputDirectories[0] stringByAppendingPathComponent:fileName];

      if (!webrtc::test::WritePerfResults([NSString stdStringForString:outputPath])) {
        exit(1);
      }
    }
  }
  if (g_metrics_to_plot) {
    webrtc::test::PrintPlottableResults(*g_metrics_to_plot);
  }

  // If a test app is too fast, it will exit before Instruments has has a
  // a chance to initialize and no test results will be seen.
  // TODO(crbug.com/137010): Figure out how much time is actually needed, and
  // sleep only to make sure that much time has elapsed since launch.
  [NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:2.0]];

  // Use the hidden selector to try and cleanly take down the app (otherwise
  // things can think the app crashed even on a zero exit status).
  UIApplication *application = [UIApplication sharedApplication];
  [application _terminateWithStatus:exitStatus];

  exit(exitStatus);
}

@end
namespace rtc {
namespace test {

// Note: This is not thread safe, and must be called from the same thread as
// runTests above.
void InitTestSuite(int (*test_suite)(void),
                   int argc,
                   char *argv[],
                   bool save_chartjson_result,
                   absl::optional<std::vector<std::string>> metrics_to_plot) {
  g_test_suite = test_suite;
  g_argc = argc;
  g_argv = argv;
  g_write_perf_output = save_chartjson_result;
  g_metrics_to_plot = std::move(metrics_to_plot);
}

void RunTestsFromIOSApp() {
  @autoreleasepool {
    exit(UIApplicationMain(g_argc, g_argv, nil, @"WebRtcUnitTestDelegate"));
  }
}
}  // namespace test
}  // namespace rtc
