// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// test w/ `dart test -N use_build_context_synchronously`

import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';

void awaitInSwitchCase(BuildContext context) async {
  await Future<void>.delayed(Duration());
  switch (1) {
    case 1:
      await Navigator.of(context).pushNamed('routeName'); // LINT
      break;
  }
}

void awaitInSwitchCase_mountedCheckBeforeSwitch(BuildContext context) async {
  await Future<void>.delayed(Duration());
  if (!mounted) return;
  switch (1) {
    case 1:
      await Navigator.of(context).pushNamed('routeName'); // OK
      break;
  }
}

bool get mounted => true;

BuildContext? get contextOrNull => null;

class ContextHolder {
  BuildContext? get contextOrNull => null;
}

void f2(BuildContext? contextOrNull) {}

void nullableContext() async {
  f2(contextOrNull);
  await Future<void>.delayed(Duration());
  f2(contextOrNull); // OK
}

void nullableContext2(ContextHolder holder) async {
  f2(holder.contextOrNull);
  await Future<void>.delayed(Duration());
  f2(holder.contextOrNull); // OK
}

void nullableContext3() async {
  f2(contextOrNull);
  await Future<void>.delayed(Duration());
  var renderObject = contextOrNull?.findRenderObject(); // OK
}

void unawaited(Future<void> future) {}

class WidgetStateContext {
  bool get mounted => false;
}

void f(BuildContext context) {}

void func(Function f) {}

class MyWidget extends StatefulWidget {
  @override
  State createState() => _MyState();
}

void directAccess(BuildContext context) async {
  await Future<void>.delayed(Duration());

  var renderObject = context.findRenderObject(); // LINT
}

Future<bool> binaryExpression(BuildContext context) async {
  bool f2(BuildContext context) => true;

  f2(context);

  await Future<void>.delayed(Duration());

  return true || f2(context); // LINT
}

class C {
  BuildContext context;
  C(this.context);
}

class _MyState extends State<MyWidget> {
  void methodUsingStateContext1() async {
    // Uses context from State.
    Navigator.of(context).pushNamed('routeName'); // OK

    await Future<void>.delayed(Duration());

    // Not ok. Used after an async gap without checking mounted.
    Navigator.of(context).pushNamed('routeName'); // LINT
  }

  void methodUsingStateContext2() async {
    // Uses context from State.
    Navigator.of(context).pushNamed('routeName'); // OK

    await Future<void>.delayed(Duration());

    if (!mounted) return;

    // OK. mounted checked first.
    Navigator.of(context).pushNamed('routeName'); // OK
  }

  void methodUsingStateContext2a() async {
    await Future<void>.delayed(Duration());
    if (!mounted) print('oops');

    // Need a return after the mounted check.
    Navigator.of(context).pushNamed('routeName'); // LINT
  }

  void methodUsingStateContext2b() async {
    await Future<void>.delayed(Duration());
    if (!mounted) {
      print('ok');
      return;
    }

    // Mounted check does return.
    Navigator.of(context).pushNamed('routeName'); //OK
  }

  void methodUsingStateContext3() async {
    f(context);

    await Future<void>.delayed(Duration());

    f(context); // LINT
  }

  void methodUsingStateContext4() async {
    void f(BuildContext context) {}

    f(context);

    await Future<void>.delayed(Duration());

    f(context); // LINT
  }

  void methodUsingStateContext5() async {
    C(context);

    await Future<void>.delayed(Duration());

    C(context); // LINT
  }

  void methodUsingStateContext6() async {
    Future<int> f() async => Future.value(10);

    print(await f());

    C(context); // LINT
  }

  // Method given a build context to use.
  void methodWithBuildContextParameter1(BuildContext context) async {
    Navigator.of(context).pushNamed('routeName'); // OK

    await Future<void>.delayed(Duration());
    Navigator.of(context).pushNamed('routeName'); // LINT
  }

  // Same as above, but using a conditional path.
  void methodWithBuildContextParameter2(BuildContext context) async {
    if (defaultTargetPlatform == TargetPlatform.iOS) {
      await Future<void>.delayed(Duration());
    }
    Navigator.of(context).pushNamed('routeName'); // LINT
  }

  // Another conditional path.
  void methodWithBuildContextParameter2a(BuildContext context) async {
    bool f() => true;
    while (f()) {
      await Future<void>.delayed(Duration());
    }
    Navigator.of(context).pushNamed('routeName'); // LINT
  }

  // And another.
  void methodWithBuildContextParameter2b(BuildContext context) async {
    for (var i = 0; i < 1; ++i) {
      await Future<void>.delayed(Duration());
    }
    Navigator.of(context).pushNamed('routeName'); // LINT
  }

  // And another.
  void methodWithBuildContextParameter2c(BuildContext context) async {
    for (var i in [1]) {
      await Future<void>.delayed(Duration());
    }
    Navigator.of(context).pushNamed('routeName'); // LINT
  }

  // And another.
  void methodWithBuildContextParameter2d(BuildContext context) async {
    bool f() => true;
    do {
      await Future<void>.delayed(Duration());
    } while (f());
    Navigator.of(context).pushNamed('routeName'); // LINT
  }

  Future<void> methodWithBuildContextParameter2e(BuildContext context) async {
    await Future<void>.delayed(Duration());
    if (!mounted) return;
    unawaited(methodWithBuildContextParameter2e(context)); //OK
  }

  void methodWithBuildContextParameter2g(BuildContext context) async {
    await Future<void>.delayed(Duration());
    switch (1) {
      case 1:
        if (!mounted) return;
        await Navigator.of(context).pushNamed('routeName'); // OK
        break;
    }
  }

  void methodWithBuildContextParameter2i(BuildContext context) async {
    try {
      await Future<void>.delayed(Duration());
    } finally {
      if (!mounted) return;
    }

    f(context); // OK
  }

  // Mounted checks are deliberately naive.
  void methodWithBuildContextParameter3(BuildContext context) async {
    Navigator.of(context).pushNamed('routeName'); // OK

    await Future<void>.delayed(Duration());

    if (!mounted) return;

    // Mounted doesn't cover provided context but that's by design.
    Navigator.of(context).pushNamed('routeName'); // OK
  }

  void methodWithBuildContextParameter4(BuildContext context) async {
    await Future<void>.delayed(Duration());
    if (!context.mounted) return;
    await Navigator.of(context).pushNamed('routeName'); // OK
  }

  void methodWithMountedFieldCheck(
      BuildContext context, WidgetStateContext stateContext) async {
    await Future<void>.delayed(Duration());
    if (!stateContext.mounted) return;
    f(context); // OK
  }

  @override
  Widget build(BuildContext context) => Placeholder();
}

void topLevel2(BuildContext context) async {
  Navigator.of(context).pushNamed('routeName'); // OK

  await Future<void>.delayed(Duration());
  // todo (pq): consider other conditionals (for, while, do, ...)
  if (true) {
    Navigator.of(context).pushNamed('routeName'); // LINT
  }
}
