use super::*;
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct StoredFastObservation {
pub(crate) run_order: Option<u64>,
pub(crate) accept_sequence: u64,
pub(crate) request_sequence: u64,
pub(crate) requested_service_tier: String,
pub(crate) outcome: crate::fast::FastOutcome,
}
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub(crate) enum FastDisplayState {
#[default]
Off,
Unavailable,
WillRequest,
Confirmed,
Different(String),
Unconfirmed,
}
impl StoredFastObservation {
pub(crate) fn to_fast_observation(&self) -> crate::fast::FastObservation {
crate::fast::FastObservation {
requested_service_tier: self.requested_service_tier.clone(),
outcome: self.outcome.clone(),
request_sequence: self.request_sequence,
run_order: self.run_order,
}
}
}
impl FastDisplayState {
pub(crate) fn resolve(
enabled: bool,
capability: &crate::fast::FastRequestState,
observation: Option<&crate::fast::FastObservation>,
) -> Self {
if !enabled {
return Self::Off;
}
if capability
.service_tier()
.is_none_or(|service_tier| service_tier.trim().is_empty())
{
return Self::Unavailable;
}
let observation = observation.filter(|observation| {
crate::fast::fast_observation_matches_request(observation, capability)
});
match observation.map(|observation| &observation.outcome) {
Some(crate::fast::FastOutcome::Confirmed) => Self::Confirmed,
Some(crate::fast::FastOutcome::Different(service_tier)) => {
Self::Different(crate::fast::display_service_tier(service_tier))
}
Some(crate::fast::FastOutcome::Unconfirmed) => Self::Unconfirmed,
Some(crate::fast::FastOutcome::NotRequested) | None => Self::WillRequest,
}
}
}
impl MissionControlState {
pub(crate) fn refresh_fast_mode_state(
&mut self,
enabled: bool,
capability: &crate::fast::FastRequestState,
) {
let capable = capability
.service_tier()
.is_some_and(|service_tier| !service_tier.trim().is_empty());
self.fast_mode_enabled = enabled;
self.fast_mode_request_state = capability.clone();
self.fast_mode_capable = capable;
self.fast_mode_effective = enabled && capable;
}
pub(crate) fn set_fast_mode_enabled(&mut self, enabled: bool) {
self.fast_mode_enabled = enabled;
self.fast_mode_effective = enabled && self.fast_mode_capable;
}
pub(crate) fn selected_fast_observation(&self) -> Option<&StoredFastObservation> {
let key = crate::fast::canonical_fast_observation_key(&self.provider, &self.model);
self.fast_observations.get(&key)
}
pub(crate) fn fast_display_state(
&self,
enabled: bool,
capability: &crate::fast::FastRequestState,
) -> FastDisplayState {
let observation = self
.selected_fast_observation()
.map(StoredFastObservation::to_fast_observation);
FastDisplayState::resolve(enabled, capability, observation.as_ref())
}
pub(crate) fn accept_fast_observation(
&mut self,
provider_id: &str,
model: &str,
requested_service_tier: &str,
outcome: &crate::fast::FastOutcome,
request_sequence: u64,
run_order: Option<u64>,
) -> bool {
self.fast_observation_accept_sequence =
self.fast_observation_accept_sequence.saturating_add(1);
let accept_sequence = self.fast_observation_accept_sequence;
let key = crate::fast::canonical_fast_observation_key(provider_id, model);
let candidate_order = crate::fast::FastObservationOrder {
run_order,
accept_sequence,
};
let current_order =
self.fast_observations
.get(&key)
.map(|stored| crate::fast::FastObservationOrder {
run_order: stored.run_order,
accept_sequence: stored.accept_sequence,
});
if crate::fast::compare_fast_observation_order(current_order, candidate_order)
!= std::cmp::Ordering::Greater
{
return false;
}
let observation = crate::fast::FastObservation {
run_order,
request_sequence,
requested_service_tier: requested_service_tier.to_string(),
outcome: outcome.clone(),
};
self.fast_observations.insert(
key,
StoredFastObservation {
run_order,
accept_sequence,
request_sequence,
requested_service_tier: requested_service_tier.to_string(),
outcome: outcome.clone(),
},
);
if let Some(warning) =
crate::fast::fast_observation_warning(provider_id, model, &observation)
{
let warning = crate::output::sanitize_display_text(&warning);
self.status = warning.clone();
if self
.fast_warning_keys
.insert(crate::fast::canonical_fast_warning_key(
provider_id,
model,
&observation,
))
{
self.record_fast_warning_transcript(&warning);
}
}
true
}
pub(crate) fn clear_fast_observations(&mut self) {
self.fast_observations.clear();
self.fast_warning_keys.clear();
}
pub(crate) fn fast_mode_rainbow_active(&self) -> bool {
self.fast_mode_enabled
&& self.fast_mode_effective
&& self.color_enabled
&& !self.reduced_motion
&& self.provider_ready
&& (!self.provider.trim().is_empty() || !self.model.trim().is_empty())
}
pub(crate) fn advance_fast_mode_rainbow_phase(&mut self) -> bool {
if !self.fast_mode_rainbow_active() {
return false;
}
let palette_len = self.theme.fast_mode_rainbow_len();
if palette_len == 0 {
return false;
}
self.fast_mode_rainbow_phase = self.fast_mode_rainbow_phase.wrapping_add(1) % palette_len;
true
}
}