// Copyright 2014 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 'dart:async';
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter_driver/driver_extension.dart';

/// This application shows empty screen until first frame timings are acquired.
void main() {
  enableFlutterDriverExtension();

  final Completer<List<FrameTiming>> completer = Completer<List<FrameTiming>>();
  SchedulerBinding.instance!.addTimingsCallback((List<FrameTiming> timings) {
    completer.complete(timings);
  });

  runApp(Directionality(
    textDirection: TextDirection.ltr,
    child: _FirstFrameTimings(completer: completer),
  ));
}

class _FirstFrameTimings extends StatefulWidget {
  const _FirstFrameTimings({
    Key? key,
    required this.completer,
  }) : super(key: key);

  final Completer<List<FrameTiming>> completer;

  @override
  _FirstFrameTimingsState createState() => _FirstFrameTimingsState();
}

class _FirstFrameTimingsState extends State<_FirstFrameTimings> {
  int? _minFrameNumber;

  @override
  Widget build(BuildContext context) {
    widget.completer.future.then(_setMinFrameNumber);
    if (_minFrameNumber != null) {
      return Text(
        _minFrameNumber.toString(),
        key: const Key('minFrameNumber'),
      );
    } else {
      return const Text('Waiting...');
    }
  }

  void _setMinFrameNumber(List<FrameTiming> timings) {
    final int minFrameNumber = timings
      .map((FrameTiming timing) => timing.frameNumber)
      .reduce(min);
    setState(() {
      _minFrameNumber = minFrameNumber;
    });
  }
}
