// Copyright 2013 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 'package:flutter/foundation.dart'
    show immutable, objectRuntimeType, setEquals;

import 'maps_object.dart';
import 'utils/maps_object.dart';

/// Update specification for a set of objects.
@immutable
class MapsObjectUpdates<T extends MapsObject<T>> {
  /// Computes updates given previous and current object sets.
  ///
  /// [objectName] is the prefix to use when serializing the updates into a JSON
  /// dictionary. E.g., 'circle' will give 'circlesToAdd', 'circlesToUpdate',
  /// 'circleIdsToRemove'.
  MapsObjectUpdates.from(
    Set<T> previous,
    Set<T> current, {
    required this.objectName,
  }) {
    final Map<MapsObjectId<T>, T> previousObjects = keyByMapsObjectId(previous);
    final Map<MapsObjectId<T>, T> currentObjects = keyByMapsObjectId(current);

    final Set<MapsObjectId<T>> previousObjectIds = previousObjects.keys.toSet();
    final Set<MapsObjectId<T>> currentObjectIds = currentObjects.keys.toSet();

    /// Maps an ID back to a [T] in [currentObjects].
    ///
    /// It is a programming error to call this with an ID that is not guaranteed
    /// to be in [currentObjects].
    T idToCurrentObject(MapsObjectId<T> id) {
      return currentObjects[id]!;
    }

    _objectIdsToRemove = previousObjectIds.difference(currentObjectIds);

    _objectsToAdd = currentObjectIds
        .difference(previousObjectIds)
        .map(idToCurrentObject)
        .toSet();

    // Returns `true` if [current] is not equals to previous one with the
    // same id.
    bool hasChanged(T current) {
      final T? previous = previousObjects[current.mapsId];
      return current != previous;
    }

    _objectsToChange = currentObjectIds
        .intersection(previousObjectIds)
        .map(idToCurrentObject)
        .where(hasChanged)
        .toSet();
  }

  /// The name of the objects being updated, for use in serialization.
  final String objectName;

  /// Set of objects to be added in this update.
  Set<T> get objectsToAdd {
    return _objectsToAdd;
  }

  late final Set<T> _objectsToAdd;

  /// Set of objects to be removed in this update.
  Set<MapsObjectId<T>> get objectIdsToRemove {
    return _objectIdsToRemove;
  }

  late final Set<MapsObjectId<T>> _objectIdsToRemove;

  /// Set of objects to be changed in this update.
  Set<T> get objectsToChange {
    return _objectsToChange;
  }

  late final Set<T> _objectsToChange;

  /// Converts this object to JSON.
  Object toJson() {
    final Map<String, Object> updateMap = <String, Object>{};

    void addIfNonNull(String fieldName, Object? value) {
      if (value != null) {
        updateMap[fieldName] = value;
      }
    }

    addIfNonNull('${objectName}sToAdd', serializeMapsObjectSet(_objectsToAdd));
    addIfNonNull(
        '${objectName}sToChange', serializeMapsObjectSet(_objectsToChange));
    addIfNonNull(
        '${objectName}IdsToRemove',
        _objectIdsToRemove
            .map<String>((MapsObjectId<T> m) => m.value)
            .toList());

    return updateMap;
  }

  @override
  bool operator ==(Object other) {
    if (other.runtimeType != runtimeType) {
      return false;
    }
    return other is MapsObjectUpdates &&
        setEquals(_objectsToAdd, other._objectsToAdd) &&
        setEquals(_objectIdsToRemove, other._objectIdsToRemove) &&
        setEquals(_objectsToChange, other._objectsToChange);
  }

  @override
  int get hashCode => Object.hash(Object.hashAll(_objectsToAdd),
      Object.hashAll(_objectIdsToRemove), Object.hashAll(_objectsToChange));

  @override
  String toString() {
    return '${objectRuntimeType(this, 'MapsObjectUpdates')}(add: $objectsToAdd, '
        'remove: $objectIdsToRemove, '
        'change: $objectsToChange)';
  }
}
