// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// ignore_for_file: deprecated_member_use

import 'dart:async';
import 'dart:ui' as ui;

import 'package:flutter/widgets.dart';
import 'package:lib.widgets/model.dart';
import 'package:lib.widgets/utils.dart';
import 'package:lib.widgets/widgets.dart';


const RK4SpringDescription _kSimulationDesc =
    RK4SpringDescription(tension: 10.0, friction: 50.0);
const double _kMinScrollOffset = 0.0;
const double _kMaxScrollOffset = 4000.0;
const int _kNumImages = 100;

/// [Model] that manages the state of the Image Grid Module
class ImageGridModel extends Model {
  final _TracedSpringModel _scrollModel =
      _TracedSpringModel(springDescription: _kSimulationDesc);

  ImageGridModel() {
    scheduleMicrotask(() {
      generateImages().then((List<RawImage> images) {
        _images = images;
        _scrollModel.jump(0.0);

        // Set up auto-scroller behavior.
        _scrollController = ScrollController();
        _scrollModel
          ..addListener(() {
            if (!_scrollController.hasClients) {
              return;
            }
            _scrollController.jumpTo(_scrollModel.value);
            if (_scrollModel.isDone) {
              _scrollModel.target = _scrollModel.target == _kMinScrollOffset
                  ? _kMaxScrollOffset
                  : _kMinScrollOffset;
            }
          })
          ..target = _kMaxScrollOffset;
        notifyListeners();
      });
    });
  }

  // Draw some images with circles.
  Future<List<RawImage>> generateImages() async {
    List<RawImage> images = [];
    for (int i = 0; i < _kNumImages; i++) {
      var recorder = ui.PictureRecorder();
      var canvas = Canvas(recorder);
      var color = Color(0xFF673AB7); // Deep Purple 500
      canvas.drawColor(color, BlendMode.srcOver);

      final paint = Paint()
        ..color = Color(0xFFF50057) // Pink A400
        ..style = PaintingStyle.fill;

      canvas.drawCircle(Offset(250.0, 250.0), 200.0, paint);

      var image = await recorder.endRecording().toImage(500, 500);

      images
          .add(RawImage(image: image, width: 500.0, height: 500.0, scale: 1.0));
    }
    return images;
  }

  /// Images to render
  List<RawImage> get images => _images;
  List<RawImage> _images;

  /// If non-null, controls how the grid is scrolled.
  ScrollController get scrollController => _scrollController;
  ScrollController _scrollController;
}

class _TracedSpringModel extends SpringModel {
  final FrameRateTracer _frameRateTracer = FrameRateTracer(name: 'auto scroll');
  _TracedSpringModel({RK4SpringDescription springDescription})
      : super(springDescription: springDescription);

  @override
  set target(double target) {
    _frameRateTracer.start(targetName: '$target');
    super.target = target;
  }

  @override
  bool handleTick(double elapsedSeconds) {
    _frameRateTracer.tick();
    bool result = super.handleTick(elapsedSeconds);
    if (isDone) {
      _frameRateTracer.done();
    }
    return result;
  }
}
