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

import 'package:flutter/foundation.dart';
import 'package:flutter/painting.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';

class TestAssetBundle extends CachingAssetBundle {
  TestAssetBundle(this._assetBundleMap);

  final Map<String, List<Map<Object?, Object?>>> _assetBundleMap;

  Map<String, int> loadCallCount = <String, int>{};

  @override
  Future<ByteData> load(String key) async {
    if (key == 'AssetManifest.bin') {
      return const StandardMessageCodec().encodeMessage(_assetBundleMap)!;
    }

    if (key == 'AssetManifest.bin.json') {
      // Encode the manifest data that will be used by the app
      final ByteData data = const StandardMessageCodec().encodeMessage(_assetBundleMap)!;
      // Simulate the behavior of NetworkAssetBundle.load here, for web tests
      return ByteData.sublistView(
        utf8.encode(
          json.encode(
            base64.encode(
              // Encode only the actual bytes of the buffer, and no more...
              data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes)
            )
          )
        )
      );
    }

    loadCallCount[key] = loadCallCount[key] ?? 0 + 1;
    if (key == 'one') {
      return ByteData(1)
        ..setInt8(0, 49);
    }
    throw FlutterError('key not found');
  }

  @override
  Future<ui.ImmutableBuffer> loadBuffer(String key) async {
    final ByteData data = await load(key);
    return ui.ImmutableBuffer.fromUint8List(data.buffer.asUint8List());
  }
}

void main() {
  group('1.0 scale device tests', () {
    void buildAndTestWithOneAsset(String mainAssetPath) {
      final Map<String, List<Map<Object?, Object?>>> assetBundleMap =
        <String, List<Map<Object?, Object?>>>{};

      final AssetImage assetImage = AssetImage(
        mainAssetPath,
        bundle: TestAssetBundle(assetBundleMap),
      );
      const ImageConfiguration configuration = ImageConfiguration.empty;

      assetImage.obtainKey(configuration)
        .then(expectAsync1((AssetBundleImageKey bundleKey) {
          expect(bundleKey.name, mainAssetPath);
          expect(bundleKey.scale, 1.0);
        }));
    }

    test('When asset is main variant check scale is 1.0', () {
      buildAndTestWithOneAsset('assets/normalFolder/normalFile.png');
    });

    test('When asset path and key are the same string even though it could be took as a 3.0x variant', () async {
      buildAndTestWithOneAsset('assets/parentFolder/3.0x/normalFile.png');
    });

    test('When asset path contains variant identifier as part of parent folder name scale is 1.0', () {
      buildAndTestWithOneAsset('assets/parentFolder/__3.0x__/leafFolder/normalFile.png');
    });

    test('When asset path contains variant identifier as part of leaf folder name scale is 1.0', () {
      buildAndTestWithOneAsset('assets/parentFolder/__3.0x_leaf_folder_/normalFile.png');
    });

    test('When asset path contains variant identifier as part of parent folder name scale is 1.0', () {
      buildAndTestWithOneAsset('assets/parentFolder/__3.0x__/leafFolder/normalFile.png');
    });

    test('When asset path contains variant identifier in parent folder scale is 1.0', () {
      buildAndTestWithOneAsset('assets/parentFolder/3.0x/leafFolder/normalFile.png');
    });
  });


  group('High-res device behavior tests', () {
    test('When asset is not main variant check scale is not 1.0', () {
      const String mainAssetPath = 'assets/normalFolder/normalFile.png';
      const String variantPath = 'assets/normalFolder/3.0x/normalFile.png';

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

      final Map<Object?, Object?> mainAssetVariantManifestEntry = <Object?, Object?>{};
      mainAssetVariantManifestEntry['asset'] = variantPath;
      mainAssetVariantManifestEntry['dpr'] = 3.0;
      assetBundleMap[mainAssetPath] = <Map<Object?, Object?>>[mainAssetVariantManifestEntry];
      final TestAssetBundle testAssetBundle = TestAssetBundle(assetBundleMap);

      final AssetImage assetImage = AssetImage(
        mainAssetPath,
        bundle: testAssetBundle,
      );

      assetImage.obtainKey(ImageConfiguration.empty)
        .then(expectAsync1((AssetBundleImageKey bundleKey) {
          expect(bundleKey.name, mainAssetPath);
          expect(bundleKey.scale, 1.0);
        }));

      assetImage.obtainKey(ImageConfiguration(
        bundle: testAssetBundle,
        devicePixelRatio: 3.0,
      )).then(expectAsync1((AssetBundleImageKey bundleKey) {
        expect(bundleKey.name, variantPath);
        expect(bundleKey.scale, 3.0);
      }));
    });

    test('When high-res device and high-res asset not present in bundle then return main variant', () {
      const String mainAssetPath = 'assets/normalFolder/normalFile.png';

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

      assetBundleMap[mainAssetPath] = <Map<Object?, Object?>>[];

      final TestAssetBundle testAssetBundle = TestAssetBundle(assetBundleMap);

      final AssetImage assetImage = AssetImage(
        mainAssetPath,
        bundle: TestAssetBundle(assetBundleMap),
      );


      assetImage.obtainKey(ImageConfiguration.empty)
        .then(expectAsync1((AssetBundleImageKey bundleKey) {
          expect(bundleKey.name, mainAssetPath);
          expect(bundleKey.scale, 1.0);
        }));

      assetImage.obtainKey(ImageConfiguration(
        bundle: testAssetBundle,
        devicePixelRatio: 3.0,
      )).then(expectAsync1((AssetBundleImageKey bundleKey) {
        expect(bundleKey.name, mainAssetPath);
        expect(bundleKey.scale, 1.0);
      }));
    });
  });

  group('Regression - When assets available are 1.0 and 3.0 check devices with a range of scales', () {
    const String mainAssetPath = 'assets/normalFolder/normalFile.png';
    const String variantPath = 'assets/normalFolder/3.0x/normalFile.png';


    void buildBundleAndTestVariantLogic(
      double deviceRatio,
      double chosenAssetRatio,
      String expectedAssetPath,
    ) {
      const Map<String, List<Map<Object?, Object?>>> assetManifest =
          <String, List<Map<Object?, Object?>>>{
        'assets/normalFolder/normalFile.png': <Map<Object?, Object?>>[
          <Object?, Object?>{'asset': 'assets/normalFolder/normalFile.png'},
          <Object?, Object?>{
            'asset': 'assets/normalFolder/3.0x/normalFile.png',
            'dpr': 3.0
          },
        ]
      };
      final TestAssetBundle testAssetBundle = TestAssetBundle(assetManifest);

      final AssetImage assetImage = AssetImage(
        mainAssetPath,
        bundle: testAssetBundle,
      );

      // we have 1.0 and 3.0, asking for 1.5 should give
      assetImage.obtainKey(ImageConfiguration(
        bundle: testAssetBundle,
        devicePixelRatio: deviceRatio,
      )).then(expectAsync1((AssetBundleImageKey bundleKey) {
        expect(bundleKey.name, expectedAssetPath);
        expect(bundleKey.scale, chosenAssetRatio);
      }));
    }

    test('Obvious case 1.0 - we have exact asset', () {
      buildBundleAndTestVariantLogic(1.0, 1.0, mainAssetPath);
    });

    test('Obvious case 3.0 - we have exact asset', () {
      buildBundleAndTestVariantLogic(3.0, 3.0, variantPath);
    });

    test('Typical case 2.0', () {
      buildBundleAndTestVariantLogic(2.0, 1.0, mainAssetPath);
    });

    test('Borderline case 2.01', () {
      buildBundleAndTestVariantLogic(2.01, 3.0, variantPath);
    });
    test('Borderline case 2.9', () {
      buildBundleAndTestVariantLogic(2.9, 3.0, variantPath);
    });

    test('Typical case 4.0', () {
      buildBundleAndTestVariantLogic(4.0, 3.0, variantPath);
    });
  });

}
