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

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:go_router/go_router.dart';

import 'test_helpers.dart';

void main() {
  testWidgets('router rebuild with extra codec works',
      (WidgetTester tester) async {
    const String initialString = 'some string';
    const String empty = 'empty';
    final GoRouter router = GoRouter(
      initialLocation: '/',
      extraCodec: ComplexDataCodec(),
      initialExtra: ComplexData(initialString),
      routes: <RouteBase>[
        GoRoute(
            path: '/',
            builder: (_, GoRouterState state) {
              return Text((state.extra as ComplexData?)?.data ?? empty);
            }),
      ],
      redirect: (BuildContext context, _) {
        // Set up dependency.
        SimpleDependencyProvider.of(context);
        return null;
      },
    );

    addTearDown(router.dispose);
    final SimpleDependency dependency = SimpleDependency();
    addTearDown(() => dependency.dispose());

    await tester.pumpWidget(
      SimpleDependencyProvider(
        dependency: dependency,
        child: MaterialApp.router(
          routerConfig: router,
        ),
      ),
    );
    expect(find.text(initialString), findsOneWidget);
    dependency.boolProperty = !dependency.boolProperty;

    await tester.pumpAndSettle();
    expect(find.text(initialString), findsOneWidget);
  });

  testWidgets('Restores state correctly', (WidgetTester tester) async {
    const String initialString = 'some string';
    const String empty = 'empty';
    final List<RouteBase> routes = <RouteBase>[
      GoRoute(
        path: '/',
        builder: (_, GoRouterState state) {
          return Text((state.extra as ComplexData?)?.data ?? empty);
        },
      ),
    ];

    await createRouter(
      routes,
      tester,
      initialExtra: ComplexData(initialString),
      restorationScopeId: 'test',
      extraCodec: ComplexDataCodec(),
    );
    expect(find.text(initialString), findsOneWidget);

    await tester.restartAndRestore();

    await tester.pumpAndSettle();
    expect(find.text(initialString), findsOneWidget);
  });
}

class ComplexData {
  ComplexData(this.data);
  final String data;
}

class ComplexDataCodec extends Codec<ComplexData?, Object?> {
  @override
  Converter<Object?, ComplexData?> get decoder => ComplexDataDecoder();
  @override
  Converter<ComplexData?, Object?> get encoder => ComplexDataEncoder();
}

class ComplexDataDecoder extends Converter<Object?, ComplexData?> {
  @override
  ComplexData? convert(Object? input) {
    if (input == null) {
      return null;
    }
    return ComplexData(input as String);
  }
}

class ComplexDataEncoder extends Converter<ComplexData?, Object?> {
  @override
  Object? convert(ComplexData? input) {
    if (input == null) {
      return null;
    }
    return input.data;
  }
}
