import "models.dart";

/// The parts a service record can say were changed.
///
/// One list, because each part has to appear in three places at once — the
/// Changed parts section of the service form, the parts column of a service
/// card, and the panel that column opens — and three hand-kept copies would
/// drift the first time somebody adds a part. Adding one here (plus its boolean
/// on the API's service_records collection) is the whole job.
///
/// Mirrors SERVICE_PARTS in the web app's lib/serviceParts.js. The two lists
/// share the [label] keys on purpose: a part named one thing here and another
/// there would be the same service reading differently on the two screens.
class ServicePart {
  /// What the part is known by wherever a part has to be identified. Not a
  /// column key — every part shares the one "parts" column, which is what keeps
  /// the table from widening as parts are added.
  final String key;

  /// The record's own boolean, as the API names it in JSON. Only the form needs
  /// it, to build the payload it sends.
  final String field;

  /// The translation key, shared with the form so the card and the dialog
  /// cannot end up wording the same part differently.
  final String label;

  /// The shorter wording, for the chip on a service card. A chip has room for a
  /// phrase and not a sentence; the web's table cell has the same problem and
  /// answers it by truncating the list instead.
  final String chipLabel;

  /// What a *new* record starts with: an oil change is the reason for most
  /// services, the filters are the exception.
  final bool initial;

  /// Whether this record says the part was changed. A function rather than the
  /// field name because Dart cannot index a class the way the web app indexes
  /// the record object it got back as JSON.
  final bool Function(ServiceRecord) changed;

  const ServicePart({
    required this.key,
    required this.field,
    required this.label,
    required this.chipLabel,
    required this.initial,
    required this.changed,
  });
}

final List<ServicePart> kServiceParts = [
  ServicePart(
    key: "oil",
    field: "changedOil",
    label: "forms.service.oil",
    chipLabel: "car.services.chipOil",
    initial: true,
    changed: (s) => s.changedOil,
  ),
  ServicePart(
    key: "engineFilter",
    field: "changedEngineAirFilter",
    label: "forms.service.engineFilter",
    chipLabel: "car.services.chipEngineFilter",
    initial: false,
    changed: (s) => s.changedEngineAirFilter,
  ),
  ServicePart(
    key: "cabinFilter",
    field: "changedCabinAirFilter",
    label: "forms.service.cabinFilter",
    chipLabel: "car.services.chipCabinFilter",
    initial: false,
    changed: (s) => s.changedCabinAirFilter,
  ),
];

/// The parts a car actually records, which is every one it hasn't switched off.
/// An EV changes no oil, and a checkbox nobody will ever tick is one more thing
/// to read past on every service. The hidden set rather than the visible one, so
/// a part added in a later release is on by default.
List<ServicePart> visibleParts(Car car) =>
    kServiceParts.where((part) => !car.hiddenServiceParts.contains(part.key)).toList();

/// The parts this record says were changed, among the ones [parts] still shows.
/// A record written before a part existed simply doesn't carry its field, which
/// the model reads as false — "not changed" rather than "unknown", because that
/// service genuinely didn't change it.
///
/// A part switched off disappears from the history as well as from the form, the
/// same way a hidden column does: what "I don't record this" means is that it
/// stops taking up room, not that it takes up room saying nothing. Its stored
/// boolean is left alone, so switching it back on brings the old records' chips
/// back with it.
List<ServicePart> changedParts(ServiceRecord service, List<ServicePart> parts) =>
    parts.where((part) => part.changed(service)).toList();
