// 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:async';
import 'dart:convert';
import 'dart:typed_data';
import 'dart:ui';

import 'package:litetest/litetest.dart';

void main() {
  test('Loading an asset that does not exist returns null', () async {
    Object? error;
    try {
      await ImmutableBuffer.fromAsset('ThisDoesNotExist');
    } catch (err) {
      error = err;
    }
    expect(error, isNotNull);
    expect(error is Exception, true);
  });

  test('Loading a file that does not exist returns null', () async {
    Object? error;
    try {
      await ImmutableBuffer.fromFilePath('ThisDoesNotExist');
    } catch (err) {
      error = err;
    }
    expect(error, isNotNull);
    expect(error is Exception, true);
  });

  test('returns the bytes of a bundled asset', () async {
    final ImmutableBuffer buffer = await ImmutableBuffer.fromAsset('DashInNooglerHat.jpg');

    expect(buffer.length == 354679, true);
  });

  test('returns the bytes of a file', () async {
    final ImmutableBuffer buffer = await ImmutableBuffer.fromFilePath('flutter/lib/ui/fixtures/DashInNooglerHat.jpg');

    expect(buffer.length == 354679, true);
  });

  test('Can load an asset with a space in the key', () async {
    // This assets actual path is "fixtures/DashInNooglerHat%20WithSpace.jpg"
    final ImmutableBuffer buffer = await ImmutableBuffer.fromAsset('DashInNooglerHat WithSpace.jpg');

    expect(buffer.length == 354679, true);
  });

  test('can dispose immutable buffer', () async {
    final ImmutableBuffer buffer = await ImmutableBuffer.fromAsset('DashInNooglerHat.jpg');

    buffer.dispose();
  });

  test('Tester can disable loading fonts from an asset bundle', () async {
    final List<int> ahemImage = await _createPictureFromFont('Ahem');
    // Font that is bundled in the asset directory of the test runner.
    final List<int> bundledFontImage = await _createPictureFromFont('Roboto');
    // Bundling fonts is disabled, so the font selected in both cases should be ahem.
    // Therefore each buffer will contain identical contents.
    expect(ahemImage, equals(bundledFontImage));
  });

  test('Tester can still load through dart:ui', () async {
    /// Manually load font asset through dart.
    final Uint8List encoded = utf8.encode(Uri(path: Uri.encodeFull('Roboto-Medium.ttf')).path);
    final Completer<Uint8List> result = Completer<Uint8List>();
    PlatformDispatcher.instance.sendPlatformMessage('flutter/assets', encoded.buffer.asByteData(), (ByteData? data) {
      result.complete(data!.buffer.asUint8List());
    });

    await loadFontFromList(await result.future, fontFamily: 'Roboto2');

    final List<int> ahemImage = await _createPictureFromFont('Ahem');
    // Font that is bundled in the asset directory of the test runner.
    final List<int> bundledFontImage = await _createPictureFromFont('Roboto2');
    // Bundling fonts is disabled, so the font selected in both cases should be ahem.
    // Therefore each buffer will contain identical contents.
    expect(ahemImage, notEquals(bundledFontImage));
  });
}

Future<List<int>> _createPictureFromFont(String fontFamily) async {
  final ParagraphBuilder builder = ParagraphBuilder(ParagraphStyle(
    fontFamily: fontFamily,
    fontStyle: FontStyle.normal,
    fontWeight: FontWeight.normal,
    fontSize: 20,
  ));
  builder.addText('Test');
  final Paragraph paragraph = builder.build();
  paragraph.layout(const ParagraphConstraints(width: 20 * 5.0));

  final PictureRecorder recorder = PictureRecorder();
  final Canvas canvas = Canvas(recorder);
  canvas.drawParagraph(paragraph, Offset.zero);

  final Picture picture = recorder.endRecording();
  final Image image = await picture.toImage(100, 100);
  final ByteData? data = await image.toByteData();
  return data!.buffer.asUint8List().toList();
}
