// 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:ui' as ui show lerpDouble;

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

import 'framework.dart' show BuildContext;

/// Defines the size, font variations, color, opacity, and shadows of icons.
///
/// Used by [IconTheme] to control those properties in a widget subtree.
///
/// To obtain the current icon theme, use [IconTheme.of]. To convert an icon
/// theme to a version with all the fields filled in, use
/// [IconThemeData.fallback].
@immutable
class IconThemeData with Diagnosticable {
  /// Creates an icon theme data.
  ///
  /// The opacity applies to both explicit and default icon colors. The value
  /// is clamped between 0.0 and 1.0.
  const IconThemeData({
    this.size,
    this.fill,
    this.weight,
    this.grade,
    this.opticalSize,
    this.color,
    double? opacity,
    this.shadows,
  }) : _opacity = opacity,
       assert(fill == null || (0.0 <= fill && fill <= 1.0)),
       assert(weight == null || (0.0 < weight)),
       assert(opticalSize == null || (0.0 < opticalSize));

  /// Creates an icon theme with some reasonable default values.
  ///
  /// The [size] is 24.0, [fill] is 0.0, [weight] is 400.0, [grade] is 0.0,
  /// opticalSize is 48.0, [color] is black, and [opacity] is 1.0.
  const IconThemeData.fallback()
      : size = 24.0,
        fill = 0.0,
        weight = 400.0,
        grade = 0.0,
        opticalSize = 48.0,
        color = const Color(0xFF000000),
        _opacity = 1.0,
        shadows = null;

  /// Creates a copy of this icon theme but with the given fields replaced with
  /// the new values.
  IconThemeData copyWith({
    double? size,
    double? fill,
    double? weight,
    double? grade,
    double? opticalSize,
    Color? color,
    double? opacity,
    List<Shadow>? shadows,
  }) {
    return IconThemeData(
      size: size ?? this.size,
      fill: fill ?? this.fill,
      weight: weight ?? this.weight,
      grade: grade ?? this.grade,
      opticalSize: opticalSize ?? this.opticalSize,
      color: color ?? this.color,
      opacity: opacity ?? this.opacity,
      shadows: shadows ?? this.shadows,
    );
  }

  /// Returns a new icon theme that matches this icon theme but with some values
  /// replaced by the non-null parameters of the given icon theme. If the given
  /// icon theme is null, simply returns this icon theme.
  IconThemeData merge(IconThemeData? other) {
    if (other == null) {
      return this;
    }
    return copyWith(
      size: other.size,
      fill: other.fill,
      weight: other.weight,
      grade: other.grade,
      opticalSize: other.opticalSize,
      color: other.color,
      opacity: other.opacity,
      shadows: other.shadows,
    );
  }

  /// Called by [IconTheme.of] to convert this instance to an [IconThemeData]
  /// that fits the given [BuildContext].
  ///
  /// This method gives the ambient [IconThemeData] a chance to update itself,
  /// after it's been retrieved by [IconTheme.of], and before being returned as
  /// the final result. For instance, [CupertinoIconThemeData] overrides this method
  /// to resolve [color], in case [color] is a [CupertinoDynamicColor] and needs
  /// to be resolved against the given [BuildContext] before it can be used as a
  /// regular [Color].
  ///
  /// The default implementation returns this [IconThemeData] as-is.
  ///
  /// See also:
  ///
  ///  * [CupertinoIconThemeData.resolve] an implementation that resolves
  ///    the color of [CupertinoIconThemeData] before returning.
  IconThemeData resolve(BuildContext context) => this;

  /// Whether all the properties (except shadows) of this object are non-null.
  bool get isConcrete => size != null
    && fill != null
    && weight != null
    && grade != null
    && opticalSize != null
    && color != null
    && opacity != null;

  /// The default for [Icon.size].
  ///
  /// Falls back to 24.0.
  final double? size;

  /// The default for [Icon.fill].
  ///
  /// Falls back to 0.0.
  final double? fill;

  /// The default for [Icon.weight].
  ///
  /// Falls back to 400.0.
  final double? weight;

  /// The default for [Icon.grade].
  ///
  /// Falls back to 0.0.
  final double? grade;

  /// The default for [Icon.opticalSize].
  ///
  /// Falls back to 48.0.
  final double? opticalSize;

  /// The default for [Icon.color].
  ///
  /// In material apps, if there is a [Theme] without any [IconTheme]s
  /// specified, icon colors default to white if [ThemeData.brightness] is dark
  /// and black if [ThemeData.brightness] is light.
  ///
  /// Otherwise, falls back to black.
  final Color? color;

  /// An opacity to apply to both explicit and default icon colors.
  ///
  /// Falls back to 1.0.
  double? get opacity => _opacity == null ? null : clampDouble(_opacity!, 0.0, 1.0);
  final double? _opacity;

  /// The default for [Icon.shadows].
  final List<Shadow>? shadows;

  /// Linearly interpolate between two icon theme data objects.
  ///
  /// {@macro dart.ui.shadow.lerp}
  static IconThemeData lerp(IconThemeData? a, IconThemeData? b, double t) {
    assert(t != null);
    return IconThemeData(
      size: ui.lerpDouble(a?.size, b?.size, t),
      fill: ui.lerpDouble(a?.fill, b?.fill, t),
      weight: ui.lerpDouble(a?.weight, b?.weight, t),
      grade: ui.lerpDouble(a?.grade, b?.grade, t),
      opticalSize: ui.lerpDouble(a?.opticalSize, b?.opticalSize, t),
      color: Color.lerp(a?.color, b?.color, t),
      opacity: ui.lerpDouble(a?.opacity, b?.opacity, t),
      shadows: Shadow.lerpList(a?.shadows, b?.shadows, t),
    );
  }

  @override
  bool operator ==(Object other) {
    if (other.runtimeType != runtimeType) {
      return false;
    }
    return other is IconThemeData
        && other.size == size
        && other.fill == fill
        && other.weight == weight
        && other.grade == grade
        && other.opticalSize == opticalSize
        && other.color == color
        && other.opacity == opacity
        && listEquals(other.shadows, shadows);
  }

  @override
  int get hashCode => Object.hash(
    size,
    fill,
    weight,
    grade,
    opticalSize,
    color,
    opacity,
    shadows == null ? null : Object.hashAll(shadows!),
  );

  @override
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    super.debugFillProperties(properties);
    properties.add(DoubleProperty('size', size, defaultValue: null));
    properties.add(DoubleProperty('fill', fill, defaultValue: null));
    properties.add(DoubleProperty('weight', weight, defaultValue: null));
    properties.add(DoubleProperty('grade', grade, defaultValue: null));
    properties.add(DoubleProperty('opticalSize', opticalSize, defaultValue: null));
    properties.add(ColorProperty('color', color, defaultValue: null));
    properties.add(DoubleProperty('opacity', opacity, defaultValue: null));
    properties.add(IterableProperty<Shadow>('shadows', shadows, defaultValue: null));
  }
}
