use assert_matches::assert_matches;
use assert_matches2::assert_let;
use chrono::{Datelike, TimeZone, Utc};
use eyeball_im::VectorDiff;
use futures_util::{FutureExt, StreamExt as _};
use matrix_sdk_test::{ALICE, BOB, async_test};
use ruma::{
events::{AnyMessageLikeEventContent, room::message::RoomMessageEventContent},
owned_event_id,
};
use stream_assert::assert_next_matches;
use super::TestTimeline;
use crate::timeline::{VirtualTimelineItem, traits::RoomDataProvider as _};
#[async_test]
async fn test_date_divider() {
let timeline = TestTimeline::new();
let mut stream = timeline.subscribe().await;
let f = &timeline.factory;
timeline
.handle_live_event(f.text_msg("This is a first message on the first day").sender(*ALICE))
.await;
let item = assert_next_matches!(stream, VectorDiff::PushBack { value } => value);
item.as_event().unwrap();
let date_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value);
assert_let!(VirtualTimelineItem::DateDivider(ts) = date_divider.as_virtual().unwrap());
let date = Utc.timestamp_millis_opt(ts.0.into()).single().unwrap();
assert_eq!(date.year(), 1970);
assert_eq!(date.month(), 1);
assert_eq!(date.day(), 1);
timeline
.handle_live_event(f.text_msg("This is a second message on the first day").sender(*ALICE))
.await;
let item = assert_next_matches!(stream, VectorDiff::PushBack { value } => value);
item.as_event().unwrap();
f.set_next_ts(24 * 60 * 60 * 1000);
timeline
.handle_live_event(f.text_msg("This is a first message on the next day").sender(*ALICE))
.await;
let item = assert_next_matches!(stream, VectorDiff::PushBack { value } => value);
item.as_event().unwrap();
let date_divider =
assert_next_matches!(stream, VectorDiff::Insert { index: 3, value } => value);
assert_let!(VirtualTimelineItem::DateDivider(ts) = date_divider.as_virtual().unwrap());
let date = Utc.timestamp_millis_opt(ts.0.into()).single().unwrap();
assert_eq!(date.year(), 1970);
assert_eq!(date.month(), 1);
assert_eq!(date.day(), 2);
let _ = timeline
.handle_local_event(AnyMessageLikeEventContent::RoomMessage(
RoomMessageEventContent::text_plain("A message I'm sending just now"),
))
.await;
let item = assert_next_matches!(stream, VectorDiff::PushBack { value } => value);
item.as_event().unwrap();
let date_divider =
assert_next_matches!(stream, VectorDiff::Insert { index: 5, value } => value);
assert!(date_divider.is_date_divider());
}
#[async_test]
async fn test_update_read_marker() {
let timeline = TestTimeline::new();
let mut stream = timeline.subscribe().await;
let own_user = timeline.controller.room_data_provider.own_user_id().to_owned();
let f = &timeline.factory;
timeline.handle_live_event(f.text_msg("A").sender(&own_user)).await;
let item = assert_next_matches!(stream, VectorDiff::PushBack { value } => value);
let event_id1 = item.as_event().unwrap().event_id().unwrap().to_owned();
let date_divider = assert_next_matches!(stream, VectorDiff::PushFront { value } => value);
assert!(date_divider.is_date_divider());
timeline.controller.handle_fully_read_marker(event_id1.clone()).await;
assert!(stream.next().now_or_never().is_none());
timeline.handle_live_event(f.text_msg("B").sender(&BOB)).await;
let item = assert_next_matches!(stream, VectorDiff::PushBack { value } => value);
let event_id2 = item.as_event().unwrap().event_id().unwrap().to_owned();
let item = assert_next_matches!(stream, VectorDiff::Insert { index: 2, value } => value);
assert_matches!(item.as_virtual(), Some(VirtualTimelineItem::ReadMarker));
timeline.controller.handle_fully_read_marker(event_id2.clone()).await;
assert_next_matches!(stream, VectorDiff::Remove { index: 2 });
timeline.handle_live_event(f.text_msg("C").sender(&BOB)).await;
let item = assert_next_matches!(stream, VectorDiff::PushBack { value } => value);
let event_id3 = item.as_event().unwrap().event_id().unwrap().to_owned();
let marker = assert_next_matches!(stream, VectorDiff::Insert { index: 3, value } => value);
assert!(marker.is_read_marker());
timeline.controller.handle_fully_read_marker(event_id1).await;
assert!(stream.next().now_or_never().is_none());
timeline.controller.handle_fully_read_marker(owned_event_id!("$fake_event_id")).await;
assert!(stream.next().now_or_never().is_none());
timeline.controller.handle_fully_read_marker(event_id2).await;
assert!(stream.next().now_or_never().is_none());
timeline.handle_live_event(f.text_msg("D").sender(&BOB)).await;
let item = assert_next_matches!(stream, VectorDiff::PushBack { value } => value);
let event_id4 = item.as_event().unwrap().event_id().unwrap().to_owned();
timeline.controller.handle_fully_read_marker(event_id3).await;
assert_next_matches!(stream, VectorDiff::Remove { index: 3 });
let marker = assert_next_matches!(stream, VectorDiff::Insert { index: 4, value } => value);
assert!(marker.is_read_marker());
timeline.handle_live_event(f.text_msg("E").sender(&own_user)).await;
let item = assert_next_matches!(stream, VectorDiff::PushBack { value } => value);
item.as_event().unwrap();
assert!(stream.next().now_or_never().is_none());
timeline.controller.handle_fully_read_marker(event_id4).await;
assert_next_matches!(stream, VectorDiff::Remove { index: 4 });
assert!(stream.next().now_or_never().is_none());
timeline.handle_live_event(f.text_msg("F").sender(&own_user)).await;
let item = assert_next_matches!(stream, VectorDiff::PushBack { value } => value);
item.as_event().unwrap();
timeline.handle_live_event(f.text_msg("G").sender(&own_user)).await;
let item = assert_next_matches!(stream, VectorDiff::PushBack { value } => value);
item.as_event().unwrap();
assert!(stream.next().now_or_never().is_none());
timeline.handle_live_event(f.text_msg("H").sender(&BOB)).await;
let item = assert_next_matches!(stream, VectorDiff::PushBack { value } => value);
item.as_event().unwrap();
let marker = assert_next_matches!(stream, VectorDiff::Insert { index: 8, value } => value);
assert!(marker.is_read_marker());
assert!(stream.next().now_or_never().is_none());
}