// Copyright 2015 The Chromium 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:sky' as sky;

/// A callback for when the image is available.
typedef void ImageListener(sky.Image image);

/// A handle to an image resource
///
/// ImageResource represents a handle to a [sky.Image] object. The underlying
/// image object might change over time, either because the image is animating
/// or because the underlying image resource was mutated.
class ImageResource {
  ImageResource(this._futureImage) {
    _futureImage.then(_handleImageLoaded, onError: _handleImageError);
  }

  bool _resolved = false;
  Future<sky.Image> _futureImage;
  sky.Image _image;
  final List<ImageListener> _listeners = new List<ImageListener>();

  /// The first concrete [sky.Image] object represented by this handle.
  ///
  /// Instead of receivingly only the first image, most clients will want to
  /// [addListener] to be notified whenever a a concrete image is available.
  Future<sky.Image> get first => _futureImage;

  /// Adds a listener callback that is called whenever a concrete [sky.Image]
  /// object is available. Note: If a concrete image is available currently,
  /// this object will call the listener synchronously.
  void addListener(ImageListener listener) {
    _listeners.add(listener);
    if (_resolved)
      listener(_image);
  }

  /// Stop listening for new concrete [sky.Image] objects.
  void removeListener(ImageListener listener) {
    _listeners.remove(listener);
  }

  void _handleImageLoaded(sky.Image image) {
    _image = image;
    _resolved = true;
    _notifyListeners();
  }

  void _handleImageError(e, stackTrace) {
    print('Failed to load image: $e\nStack trace: $stackTrace');
  }

  void _notifyListeners() {
    assert(_resolved);
    List<ImageListener> localListeners = new List<ImageListener>.from(_listeners);
    for (ImageListener listener in localListeners) {
      try {
        listener(_image);
      } catch(e) {
        print('Image listener had exception: $e');
      }
    }
  }
}