// 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 'package:collection/collection.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() {
  // Disconnects semantics listener for testing purposes.
  // If the test passes, LifeCycleSpy will rewire the semantics listener back.
  SwitchableSemanticsBinding.ensureInitialized();
  assert(!SwitchableSemanticsBinding.instance.semanticsEnabled);

  runApp(const LifeCycleSpy());
}

/// A Test widget that spies on app life cycle changes.
///
/// It will collect the AppLifecycleState sequence during its lifetime, and it
/// will rewire semantics harness if the sequence it receives matches the
/// expected list.
///
/// Rewiring semantics is a signal to native IOS test that the test has passed.
class LifeCycleSpy extends StatefulWidget {
  const LifeCycleSpy({super.key});

  @override
  State<LifeCycleSpy> createState() => _LifeCycleSpyState();
}

class _LifeCycleSpyState extends State<LifeCycleSpy> with WidgetsBindingObserver {
  final List<AppLifecycleState> _expectedLifeCycleSequence = <AppLifecycleState>[
    AppLifecycleState.detached,
    AppLifecycleState.inactive,
    AppLifecycleState.resumed,
  ];
  List<AppLifecycleState?>? _actualLifeCycleSequence;

  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
    _actualLifeCycleSequence =  <AppLifecycleState?>[
      ServicesBinding.instance.lifecycleState,
    ];
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    setState(() {
      _actualLifeCycleSequence = List<AppLifecycleState>.from(_actualLifeCycleSequence!);
      _actualLifeCycleSequence?.add(state);
    });
  }

  @override
  Widget build(BuildContext context) {
    if (const ListEquality<AppLifecycleState?>().equals(_actualLifeCycleSequence, _expectedLifeCycleSequence)) {
      // Rewires the semantics harness if test passes.
      SwitchableSemanticsBinding.instance.semanticsEnabled = true;
    }
    return const MaterialApp(
      title: 'Flutter View',
      home: Text('test'),
    );
  }
}

class SwitchableSemanticsBinding extends WidgetsFlutterBinding {
  static SwitchableSemanticsBinding get instance => BindingBase.checkInstance(_instance);
  static SwitchableSemanticsBinding? _instance;

  static SwitchableSemanticsBinding ensureInitialized() {
    if (_instance == null) {
      SwitchableSemanticsBinding();
    }
    return SwitchableSemanticsBinding.instance;
  }

  VoidCallback? _originalSemanticsListener;

  @override
  void initInstances() {
    super.initInstances();
    _instance = this;
    _updateHandler();
  }

  @override
  bool get semanticsEnabled => _semanticsEnabled.value;
  final ValueNotifier<bool> _semanticsEnabled = ValueNotifier<bool>(false);
  set semanticsEnabled(bool value) {
    _semanticsEnabled.value = value;
    _updateHandler();
  }

  void _updateHandler() {
    if (_semanticsEnabled.value) {
      platformDispatcher.onSemanticsEnabledChanged = _originalSemanticsListener;
      _originalSemanticsListener = null;
    } else {
      _originalSemanticsListener = platformDispatcher.onSemanticsEnabledChanged;
      platformDispatcher.onSemanticsEnabledChanged = null;
    }
  }

  @override
  void addSemanticsEnabledListener(VoidCallback listener) {
    _semanticsEnabled.addListener(listener);
  }

  @override
  void removeSemanticsEnabledListener(VoidCallback listener) {
    _semanticsEnabled.removeListener(listener);
  }
}
