use crate::{event_filter::EventFilter, Error};
use futures::FutureExt;
use nostr_rs_types::types::{Event, Filter};
use std::{
    future::Future,
    pin::Pin,
    task::{Context, Poll},
};

#[derive(Debug)]
pub enum FutureValue {
    Found(Result<Event, Error>),
    Pending,
    Ended,
    NotFound,
    FoundNotMatch,
}

pub type FutureResult<'a> = Pin<Box<dyn Future<Output = Result<Option<Event>, Error>> + Send + 'a>>;

pub fn check_future_call(
    future_event: &mut Option<FutureResult<'_>>,
    filter: &Option<EventFilter>,
    cx: &mut Context<'_>,
) -> FutureValue {
    if let Some(mut inner_future) = future_event.take() {
        match inner_future.poll_unpin(cx) {
            Poll::Ready(Ok(None)) => FutureValue::NotFound,
            Poll::Ready(Ok(Some(event))) => {
                // event is ready, apply the neccesary filters
                if let Some(filter) = filter {
                    if filter.check_event(&event) {
                        FutureValue::Found(Ok(event))
                    } else {
                        FutureValue::FoundNotMatch
                    }
                } else {
                    FutureValue::Found(Ok(event))
                }
            }
            Poll::Ready(Err(error)) => FutureValue::Found(Err(error)),
            Poll::Pending => {
                *future_event = Some(inner_future);
                FutureValue::Pending
            }
        }
    } else {
        FutureValue::Ended
    }
}
