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

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<String>> _assetBundleMap;

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

  String get _assetBundleContents {
    return json.encode(_assetBundleMap);
  }

  @override
  Future<ByteData> load(String key) async {
    if (key == 'AssetManifest.json')
      return ByteData.view(Uint8List.fromList(
          const Utf8Encoder().convert(_assetBundleContents)).buffer);

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

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

      assetBundleMap[mainAssetPath] = <String>[];

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

      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<String>> assetBundleMap =
      <String, List<String>>{};

      assetBundleMap[mainAssetPath] = <String>[mainAssetPath, variantPath];

      final TestAssetBundle testAssetBundle = TestAssetBundle(
          assetBundleMap);

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

      // we have the exact match for this scale, let's use it
      assetImage.obtainKey(const ImageConfiguration())
        .then(expectAsync1((AssetBundleImageKey bundleKey) {
          expect(bundleKey.name, mainAssetPath);
          expect(bundleKey.scale, 1.0);
        }));

      // we also have the exact match for this scale, let's use it
      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<String>> assetBundleMap =
      <String, List<String>>{};

      assetBundleMap[mainAssetPath] = <String>[mainAssetPath];

      final TestAssetBundle testAssetBundle = TestAssetBundle(
          assetBundleMap);

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


      assetImage.obtainKey(const ImageConfiguration())
        .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,
    ) {
      final Map<String, List<String>> assetBundleMap =
      <String, List<String>>{};

      assetBundleMap[mainAssetPath] = <String>[mainAssetPath, variantPath];

      final TestAssetBundle testAssetBundle = TestAssetBundle(
          assetBundleMap);

      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);
    });
  });

}
