namespace Flaro.Core.Playback;
/// Was ein Benutzer mit einem Titel zu tun hatte.
///
///
///
/// Je Benutzer, nicht je Server. Zwei Leute im selben Haushalt stehen
/// an verschiedenen Stellen desselben Films, und wessen Stand gilt, darf
/// nicht davon abhängen, wer zuletzt geschaut hat.
///
///
/// Der Verweis zeigt auf Film oder Folge, wie bei
/// MediaFile. Eine gemeinsame Kennung mit einem Typfeld daneben wäre
/// kürzer, aber die Datenbank könnte dann nicht mehr dafür einstehen, dass
/// der Verweis irgendwohin zeigt.
///
///
public sealed class UserItemState
{
public Guid Id { get; init; } = Guid.CreateVersion7();
public required Guid UserId { get; init; }
public Guid? MovieId { get; init; }
public Guid? EpisodeId { get; init; }
/// Die Serie als Ganzes — für Favorit, Bewertung und das Häkchen.
///
///
///
/// Eine Serie wird nicht angeschaut, ihre Folgen werden es — das
/// bleibt richtig, und deshalb steht hier kein Fortschritt. Was hier steht,
/// ist, was sich an einer Folge nicht festmachen lässt: ob die Serie ein
/// Favorit ist, wie der Benutzer sie bewertet, und ob er sie für erledigt
/// erklärt hat.
///
///
/// Warum überhaupt eine Zeile und nicht nur gezählte Folgen. Ohne
/// sie lief jede Aktion auf einer Serienkachel — Häkchen, Favorit — in eine
/// 404: der Server kannte zu dieser Kennung keinen Zustand. Sichtbar war
/// davon nichts; der Klick tat einfach nichts.
///
///
public Guid? SeriesId { get; init; }
/// Wo der Benutzer steht.
///
///
/// Ab der ersten Sekunde, ohne untere Schwelle. Das ist der
/// Unterschied, um dessentwillen dieser Server existiert — siehe
/// .
///
public TimeSpan Position { get; set; }
/// Wie lang der Titel ist, so wie der Client es gemeldet hat.
///
///
/// Hier abgelegt, damit „wie weit ist er" ohne einen Blick in die Dateien
/// zu beantworten ist. Bei zwei Fassungen eines Films — 4K und 1080p —
/// können sich die Laufzeiten um Sekunden unterscheiden; was zählt, ist
/// die, gegen die gemessen wurde.
///
public TimeSpan? Runtime { get; set; }
public bool Watched { get; set; }
public int PlayCount { get; set; }
public DateTimeOffset? LastPlayedAt { get; set; }
/// Aus „Weiterschauen" genommen, ohne als gesehen zu gelten.
///
///
/// Der Fall, für den es sonst nichts gibt. Nach einer halben Stunde
/// keine Lust mehr — der Film ist weder gesehen noch ungesehen, er soll
/// nur nicht weiter oben stehen. „Als gesehen" wäre eine Lüge, „als
/// ungesehen" täte nichts: die Position bliebe.
///
/// Die Position bleibt auch hier erhalten. Wer doch weitermacht, fängt
/// nicht von vorn an.
///
public bool Dismissed { get; set; }
public bool Favourite { get; set; }
/// Eine eigene Bewertung von 1 bis 10, oder keine.
public int? Rating { get; set; }
/// Ob dieser Titel in „Weiterschauen" gehört.
///
///
/// Kein zweites Urteil, sondern das festgehaltene Ergebnis des
/// ersten. Geschrieben wird es ausschliesslich aus
/// , bei jeder
/// Änderung an dieser Zeile.
///
/// Warum überhaupt eine Spalte: die Regel vergleicht die Stelle mit einem
/// Anteil der Laufzeit, und diese Rechnung lässt sich nicht nach SQL
/// übersetzen. Die Regel daneben ein zweites Mal als Abfrage zu schreiben
/// wäre die Variante, bei der beide irgendwann auseinanderlaufen — und
/// zwar unbemerkt, weil keine von beiden dabei falsch aussieht.
///
public bool InProgress { get; set; }
public DateTimeOffset UpdatedAt { get; set; } = DateTimeOffset.UtcNow;
}