// 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:convert';

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

void main() {
  StructureErrorTestWidgetInspectorService.runTests();
}

typedef InspectorServiceExtensionCallback = FutureOr<Map<String, Object?>> Function(Map<String, String> parameters);

class StructureErrorTestWidgetInspectorService extends Object with WidgetInspectorService {
  final Map<String, InspectorServiceExtensionCallback> extensions = <String, InspectorServiceExtensionCallback>{};

  final Map<String, List<Map<Object, Object?>>> eventsDispatched = <String, List<Map<Object, Object?>>>{};

  @override
  void registerServiceExtension({
    required String name,
    required FutureOr<Map<String, Object?>> callback(Map<String, String> parameters),
  }) {
    assert(!extensions.containsKey(name));
    extensions[name] = callback;
  }

  @override
  void postEvent(String eventKind, Map<Object, Object?> eventData) {
    getEventsDispatched(eventKind).add(eventData);
  }

  List<Map<Object, Object?>> getEventsDispatched(String eventKind) {
    return eventsDispatched.putIfAbsent(eventKind, () => <Map<Object, Object?>>[]);
  }

  Iterable<Map<Object, Object?>> getServiceExtensionStateChangedEvents(String extensionName) {
    return getEventsDispatched('Flutter.ServiceExtensionStateChanged')
      .where((Map<Object, Object?> event) => event['extension'] == extensionName);
  }

  Future<String> testBoolExtension(String name, Map<String, String> arguments) async {
    expect(extensions, contains(name));
    // Encode and decode to JSON to match behavior using a real service
    // extension where only JSON is allowed.
    return json.decode(json.encode(await extensions[name]!(arguments)))['enabled'] as String;
  }


  static void runTests() {
    final StructureErrorTestWidgetInspectorService service = StructureErrorTestWidgetInspectorService();
    WidgetInspectorService.instance = service;

    test('ext.flutter.inspector.structuredErrors still report error to original on error', () async {
      final FlutterExceptionHandler? oldHandler = FlutterError.onError;

      late FlutterErrorDetails actualError;
      // Creates a spy onError. This spy needs to be set before widgets binding
      // initializes.
      FlutterError.onError = (FlutterErrorDetails details) {
        actualError = details;
      };

      WidgetsFlutterBinding.ensureInitialized();
      try {
        // Enables structured errors.
        expect(await service.testBoolExtension(
          'structuredErrors', <String, String>{'enabled': 'true'}),
          equals('true'));

        // Creates an error.
        final FlutterErrorDetails expectedError = FlutterErrorDetails(
          library: 'rendering library',
          context: ErrorDescription('during layout'),
          exception: StackTrace.current,
        );
        FlutterError.reportError(expectedError);

        // Validates the spy still received an error.
        expect(actualError, expectedError);
      } finally {
        FlutterError.onError = oldHandler;
      }
    });
  }
}
