// 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 camera;
@import XCTest;

@interface ThreadSafeFlutterResultTests : XCTestCase
@end

@implementation ThreadSafeFlutterResultTests
- (void)testAsyncSendSuccess_ShouldCallResultOnMainThread {
  XCTestExpectation* expectation = [self expectationWithDescription:@"Result finished"];

  FLTThreadSafeFlutterResult* threadSafeFlutterResult =
      [[FLTThreadSafeFlutterResult alloc] initWithResult:^(id _Nullable result) {
        XCTAssert(NSThread.isMainThread);
        [expectation fulfill];
      }];
  dispatch_queue_t dispatchQueue = dispatch_queue_create("test dispatchqueue", NULL);
  dispatch_async(dispatchQueue, ^{
    [threadSafeFlutterResult sendSuccess];
  });

  [self waitForExpectationsWithTimeout:1 handler:nil];
}

- (void)testSyncSendSuccess_ShouldCallResultOnMainThread {
  XCTestExpectation* expectation = [self expectationWithDescription:@"Result finished"];

  FLTThreadSafeFlutterResult* threadSafeFlutterResult =
      [[FLTThreadSafeFlutterResult alloc] initWithResult:^(id _Nullable result) {
        XCTAssert(NSThread.isMainThread);
        [expectation fulfill];
      }];
  [threadSafeFlutterResult sendSuccess];
  [self waitForExpectationsWithTimeout:1 handler:nil];
}

- (void)testSendNotImplemented_ShouldSendNotImplementedToFlutterResult {
  XCTestExpectation* expectation = [self expectationWithDescription:@"Result finished"];

  FLTThreadSafeFlutterResult* threadSafeFlutterResult =
      [[FLTThreadSafeFlutterResult alloc] initWithResult:^(id _Nullable result) {
        XCTAssert([result isKindOfClass:FlutterMethodNotImplemented.class]);
        [expectation fulfill];
      }];
  dispatch_queue_t dispatchQueue = dispatch_queue_create("test dispatchqueue", NULL);
  dispatch_async(dispatchQueue, ^{
    [threadSafeFlutterResult sendNotImplemented];
  });

  [self waitForExpectationsWithTimeout:1 handler:nil];
}

- (void)testSendErrorDetails_ShouldSendErrorToFlutterResult {
  NSString* errorCode = @"errorCode";
  NSString* errorMessage = @"message";
  NSString* errorDetails = @"error details";
  XCTestExpectation* expectation = [self expectationWithDescription:@"Result finished"];

  FLTThreadSafeFlutterResult* threadSafeFlutterResult =
      [[FLTThreadSafeFlutterResult alloc] initWithResult:^(id _Nullable result) {
        XCTAssert([result isKindOfClass:FlutterError.class]);
        FlutterError* error = (FlutterError*)result;
        XCTAssertEqualObjects(error.code, errorCode);
        XCTAssertEqualObjects(error.message, errorMessage);
        XCTAssertEqualObjects(error.details, errorDetails);
        [expectation fulfill];
      }];
  dispatch_queue_t dispatchQueue = dispatch_queue_create("test dispatchqueue", NULL);
  dispatch_async(dispatchQueue, ^{
    [threadSafeFlutterResult sendErrorWithCode:errorCode message:errorMessage details:errorDetails];
  });

  [self waitForExpectationsWithTimeout:1 handler:nil];
}

- (void)testSendNSError_ShouldSendErrorToFlutterResult {
  NSError* originalError = [[NSError alloc] initWithDomain:NSURLErrorDomain code:404 userInfo:nil];
  XCTestExpectation* expectation = [self expectationWithDescription:@"Result finished"];

  FLTThreadSafeFlutterResult* threadSafeFlutterResult =
      [[FLTThreadSafeFlutterResult alloc] initWithResult:^(id _Nullable result) {
        XCTAssert([result isKindOfClass:FlutterError.class]);
        FlutterError* error = (FlutterError*)result;
        NSString* constructedErrorCode =
            [NSString stringWithFormat:@"Error %d", (int)originalError.code];
        XCTAssertEqualObjects(error.code, constructedErrorCode);
        [expectation fulfill];
      }];
  dispatch_queue_t dispatchQueue = dispatch_queue_create("test dispatchqueue", NULL);
  dispatch_async(dispatchQueue, ^{
    [threadSafeFlutterResult sendError:originalError];
  });

  [self waitForExpectationsWithTimeout:1 handler:nil];
}

- (void)testSendResult_ShouldSendResultToFlutterResult {
  NSString* resultData = @"resultData";
  XCTestExpectation* expectation = [self expectationWithDescription:@"Result finished"];

  FLTThreadSafeFlutterResult* threadSafeFlutterResult =
      [[FLTThreadSafeFlutterResult alloc] initWithResult:^(id _Nullable result) {
        XCTAssertEqualObjects(result, resultData);
        [expectation fulfill];
      }];
  dispatch_queue_t dispatchQueue = dispatch_queue_create("test dispatchqueue", NULL);
  dispatch_async(dispatchQueue, ^{
    [threadSafeFlutterResult sendSuccessWithData:resultData];
  });

  [self waitForExpectationsWithTimeout:1 handler:nil];
}
@end
