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

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';

final TextTheme textTheme =
    Typography.material2018(platform: TargetPlatform.android)
        .black
        .merge(const TextTheme(bodyText2: TextStyle(fontSize: 12.0)));

void expectWidgetTypes(Iterable<Widget> widgets, List<Type> expected) {
  final List<Type> actual = widgets.map((Widget w) => w.runtimeType).toList();
  expect(actual, expected);
}

void expectTextStrings(Iterable<Widget> widgets, List<String> strings) {
  int currentString = 0;
  for (final Widget widget in widgets) {
    if (widget is RichText) {
      final TextSpan span = widget.text as TextSpan;
      final String text = _extractTextFromTextSpan(span);
      expect(text, equals(strings[currentString]));
      currentString += 1;
    }
  }
}

String _extractTextFromTextSpan(TextSpan span) {
  String text = span.text ?? '';
  if (span.children != null) {
    for (final TextSpan child in span.children! as Iterable<TextSpan>) {
      text += _extractTextFromTextSpan(child);
    }
  }
  return text;
}

// Check the font style and weight of the text span.
void expectTextSpanStyle(
    TextSpan textSpan, FontStyle? style, FontWeight weight) {
  // Verify a text style is set
  expect(textSpan.style, isNotNull, reason: 'text span text style is null');

  // Font style check
  if (style == null) {
    expect(textSpan.style!.fontStyle, isNull, reason: 'font style is not null');
  } else {
    expect(textSpan.style!.fontStyle, isNotNull, reason: 'font style is null');
    expect(
      textSpan.style!.fontStyle == style,
      isTrue,
      reason: 'font style is not $style',
    );
  }

  // Font weight check
  expect(textSpan.style, isNotNull, reason: 'font style is null');
  expect(
    textSpan.style!.fontWeight == weight,
    isTrue,
    reason: 'font weight is not $weight',
  );
}

@immutable
class MarkdownLink {
  const MarkdownLink(this.text, this.destination, [this.title = '']);

  final String text;
  final String? destination;
  final String title;

  @override
  bool operator ==(Object other) =>
      other is MarkdownLink &&
      other.text == text &&
      other.destination == destination &&
      other.title == title;

  @override
  int get hashCode => '$text$destination$title'.hashCode;

  @override
  String toString() {
    return '[$text]($destination "$title")';
  }
}

/// Verify a valid link structure has been created. This routine checks for the
/// link text and the associated [TapGestureRecognizer] on the text span.
void expectValidLink(String linkText) {
  final Finder richTextFinder = find.byType(RichText);
  expect(richTextFinder, findsOneWidget);
  final RichText richText = richTextFinder.evaluate().first.widget as RichText;

  // Verify the link text.
  expect(richText.text, isNotNull);
  expect(richText.text, isA<TextSpan>());

  // Verify the link text is a onTap gesture recognizer.
  final TextSpan textSpan = richText.text as TextSpan;
  expectLinkTextSpan(textSpan, linkText);
}

void expectLinkTextSpan(TextSpan textSpan, String linkText) {
  expect(textSpan.children, isNull);
  expect(textSpan.toPlainText(), linkText);
  expect(textSpan.recognizer, isNotNull);
  expect(textSpan.recognizer, isA<TapGestureRecognizer>());
  final TapGestureRecognizer? tapRecognizer =
      textSpan.recognizer as TapGestureRecognizer?;
  expect(tapRecognizer?.onTap, isNotNull);

  // Execute the onTap callback handler.
  tapRecognizer!.onTap!();
}

void expectInvalidLink(String linkText) {
  final Finder richTextFinder = find.byType(RichText);
  expect(richTextFinder, findsOneWidget);
  final RichText richText = richTextFinder.evaluate().first.widget as RichText;

  expect(richText.text, isNotNull);
  expect(richText.text, isA<TextSpan>());
  final String text = richText.text.toPlainText();
  expect(text, linkText);

  final TextSpan textSpan = richText.text as TextSpan;
  expect(textSpan.recognizer, isNull);
}

void expectTableSize(int rows, int columns) {
  final Finder tableFinder = find.byType(Table);
  expect(tableFinder, findsOneWidget);
  final Table table = tableFinder.evaluate().first.widget as Table;

  expect(table.children.length, rows);
  for (int index = 0; index < rows; index++) {
    expect(table.children[index].children!.length, columns);
  }
}

void expectLinkTap(MarkdownLink? actual, MarkdownLink expected) {
  expect(actual, equals(expected),
      reason:
          'incorrect link tap results, actual: $actual expected: $expected');
}

String dumpRenderView() {
  return WidgetsBinding.instance!.renderViewElement!.toStringDeep().replaceAll(
      RegExp(r'SliverChildListDelegate#\d+', multiLine: true),
      'SliverChildListDelegate');
}

/// Wraps a widget with a left-to-right [Directionality] for tests.
Widget boilerplate(Widget child) {
  return Directionality(
    textDirection: TextDirection.ltr,
    child: child,
  );
}

class TestAssetBundle extends CachingAssetBundle {
  static const String manifest = r'{"assets/logo.png":["assets/logo.png"]}';

  @override
  Future<ByteData> load(String key) async {
    if (key == 'AssetManifest.json') {
      final ByteData asset =
          ByteData.view(utf8.encoder.convert(manifest).buffer);
      return Future<ByteData>.value(asset);
    } else if (key == 'assets/logo.png') {
      // The root directory tests are run from is different for 'flutter test'
      // verses 'flutter test test/*_test.dart'. Adjust the root directory
      // to access the assets directory.
      final io.Directory rootDirectory =
          io.Directory.current.path.endsWith(io.Platform.pathSeparator + 'test')
              ? io.Directory.current.parent
              : io.Directory.current;
      final io.File file =
          io.File('${rootDirectory.path}/test/assets/images/logo.png');

      final ByteData asset = ByteData.view(file.readAsBytesSync().buffer);
      if (asset == null) {
        throw FlutterError('Unable to load asset: $key');
      }
      return asset;
    } else {
      throw 'Unknown asset key: $key';
    }
  }
}
