// 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.

// This file is run as part of a reduced test set in CI on Mac and Windows
// machines.
@Tags(<String>['reduced-test-set'])

import 'package:file/file.dart';
import 'package:file/local.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:platform/platform.dart';

void main() {
  testWidgets('IconData object test', (WidgetTester tester) async {
    expect(Icons.account_balance, isNot(equals(Icons.account_box)));
    expect(Icons.account_balance.hashCode, isNot(equals(Icons.account_box.hashCode)));
    expect(Icons.account_balance, hasOneLineDescription);
  });

  testWidgets('Icons specify the material font', (WidgetTester tester) async {
    expect(Icons.clear.fontFamily, 'MaterialIcons');
    expect(Icons.search.fontFamily, 'MaterialIcons');
  });

  testWidgets('Certain icons (and their variants) match text direction', (WidgetTester tester) async {
    expect(Icons.arrow_back.matchTextDirection, true);
    expect(Icons.arrow_back_rounded.matchTextDirection, true);
    expect(Icons.arrow_back_outlined.matchTextDirection, true);
    expect(Icons.arrow_back_sharp.matchTextDirection, true);

    expect(Icons.access_time.matchTextDirection, false);
    expect(Icons.access_time_rounded.matchTextDirection, false);
    expect(Icons.access_time_outlined.matchTextDirection, false);
    expect(Icons.access_time_sharp.matchTextDirection, false);
  });

  testWidgets('Adaptive icons are correct on cupertino platforms', (WidgetTester tester) async {
      expect(Icons.adaptive.arrow_back, Icons.arrow_back_ios);
      expect(Icons.adaptive.arrow_back_outlined, Icons.arrow_back_ios_outlined);
    },
    variant: const TargetPlatformVariant(<TargetPlatform>{
      TargetPlatform.iOS,
      TargetPlatform.macOS,
    }),
  );

  testWidgets('Adaptive icons are correct on non-cupertino platforms', (WidgetTester tester) async {
      expect(Icons.adaptive.arrow_back, Icons.arrow_back);
      expect(Icons.adaptive.arrow_back_outlined, Icons.arrow_back_outlined);
    },
    variant: const TargetPlatformVariant(<TargetPlatform>{
      TargetPlatform.android,
      TargetPlatform.fuchsia,
      TargetPlatform.windows,
      TargetPlatform.linux,
    }),
  );

  testWidgets('A sample of icons look as expected', (WidgetTester tester) async {
    await _loadIconFont();

    await tester.pumpWidget(MaterialApp(
      home: IconTheme(
        data: const IconThemeData(size: 200),
        child: Wrap(
          children: const <Icon>[
            Icon(Icons.ten_k),
            Icon(Icons.ac_unit),
            Icon(Icons.local_taxi),
            Icon(Icons.local_taxi_outlined),
            Icon(Icons.local_taxi_rounded),
            Icon(Icons.local_taxi_sharp),
            Icon(Icons.zoom_out_sharp),
          ],
        ),
      ),
    ));

    await expectLater(find.byType(Wrap), matchesGoldenFile('test.icons.sample.png'));
  }, skip: isBrowser); // https://github.com/flutter/flutter/issues/39998

  // Regression test for https://github.com/flutter/flutter/issues/95886
  testWidgets('Another sample of icons look as expected', (WidgetTester tester) async {
    await _loadIconFont();

    await tester.pumpWidget(MaterialApp(
      home: IconTheme(
        data: const IconThemeData(size: 200),
        child: Wrap(
          children: const <Icon>[
            Icon(Icons.water_drop),
            Icon(Icons.water_drop_outlined),
            Icon(Icons.water_drop_rounded),
            Icon(Icons.water_drop_sharp),
          ],
        ),
      ),
    ));

    await expectLater(find.byType(Wrap), matchesGoldenFile('test.icons.sample2.png'));
  }, skip: isBrowser); // https://github.com/flutter/flutter/issues/39998

  testWidgets('Another sample of icons look as expected', (WidgetTester tester) async {
    await _loadIconFont();

    await tester.pumpWidget(MaterialApp(
      home: IconTheme(
        data: const IconThemeData(size: 200),
        child: Wrap(
          children: const <Icon>[
            Icon(Icons.electric_bolt),
            Icon(Icons.electric_bolt_outlined),
            Icon(Icons.electric_bolt_rounded),
            Icon(Icons.electric_bolt_sharp),
          ],
        ),
      ),
    ));

    await expectLater(find.byType(Wrap), matchesGoldenFile('test.icons.sample3.png'));
  }, skip: isBrowser); // https://github.com/flutter/flutter/issues/39998

  // Regression test for https://github.com/flutter/flutter/issues/103202.
  testWidgets('Another sample of icons look as expected', (WidgetTester tester) async {
    await _loadIconFont();

    await tester.pumpWidget(MaterialApp(
      home: IconTheme(
        data: const IconThemeData(size: 200),
        child: Wrap(
          children: const <Icon>[
            Icon(Icons.repeat_on),
            Icon(Icons.repeat_on_outlined),
            Icon(Icons.repeat_on_rounded),
            Icon(Icons.repeat_on_sharp),
          ],
        ),
      ),
    ));

    await expectLater(find.byType(Wrap), matchesGoldenFile('test.icons.sample4.png'));
  }, skip: isBrowser); // https://github.com/flutter/flutter/issues/39998
}

// Loads the cached material icon font.
// Only necessary for golden tests. Relies on the tool updating cached assets before
// running tests.
Future<void> _loadIconFont() async {
  const FileSystem fs = LocalFileSystem();
  const Platform platform = LocalPlatform();
  final Directory flutterRoot = fs.directory(platform.environment['FLUTTER_ROOT']);

  final File iconFont = flutterRoot.childFile(
    fs.path.join(
      'bin',
      'cache',
      'artifacts',
      'material_fonts',
      'MaterialIcons-Regular.otf',
    ),
  );

  final Future<ByteData> bytes = Future<ByteData>.value(
      iconFont.readAsBytesSync().buffer.asByteData(),
  );

  await (FontLoader('MaterialIcons')..addFont(bytes)).load();
}
