use super::{ColorObject, ColorTemperatureObject};
use std::borrow::Cow;
use bacnet_types::enums::PropertyIdentifier as P;
use crate::audit::ObjectAuditPolicy;
use crate::command_source::SingleValueSource;
use crate::object_profile::ObjectProfile;
use crate::property_metadata::{
PropertyConformance::{Optional, RequiredRead, RequiredWrite},
PropertyMetadata,
PropertyWriteCapability::{Always, ReadOnly},
};
const COLOR_BASE: &[PropertyMetadata] = &[
PropertyMetadata::new(P::OBJECT_IDENTIFIER, RequiredRead, None, ReadOnly),
PropertyMetadata::new(P::OBJECT_NAME, RequiredRead, None, ReadOnly),
PropertyMetadata::new(P::OBJECT_TYPE, RequiredRead, None, ReadOnly),
PropertyMetadata::new(P::PRESENT_VALUE, RequiredWrite, None, Always),
PropertyMetadata::new(P::TRACKING_VALUE, RequiredRead, None, ReadOnly),
PropertyMetadata::new(P::COLOR_COMMAND, RequiredWrite, None, Always),
PropertyMetadata::new(P::IN_PROGRESS, RequiredRead, None, ReadOnly),
PropertyMetadata::new(P::DEFAULT_COLOR, RequiredRead, None, Always),
PropertyMetadata::new(P::DESCRIPTION, Optional, None, Always),
PropertyMetadata::new(P::DEFAULT_FADE_TIME, RequiredRead, None, Always),
PropertyMetadata::new(P::TRANSITION, Optional, None, Always),
PropertyMetadata::new(P::PROPERTY_LIST, RequiredRead, None, ReadOnly),
];
const COLOR_TEMPERATURE_BASE: &[PropertyMetadata] = &[
PropertyMetadata::new(P::OBJECT_IDENTIFIER, RequiredRead, None, ReadOnly),
PropertyMetadata::new(P::OBJECT_NAME, RequiredRead, None, ReadOnly),
PropertyMetadata::new(P::OBJECT_TYPE, RequiredRead, None, ReadOnly),
PropertyMetadata::new(P::PRESENT_VALUE, RequiredWrite, None, Always),
PropertyMetadata::new(P::TRACKING_VALUE, RequiredRead, None, ReadOnly),
PropertyMetadata::new(P::COLOR_COMMAND, RequiredWrite, None, Always),
PropertyMetadata::new(P::IN_PROGRESS, RequiredRead, None, ReadOnly),
PropertyMetadata::new(P::DEFAULT_COLOR_TEMPERATURE, RequiredRead, None, Always),
PropertyMetadata::new(P::DESCRIPTION, Optional, None, Always),
PropertyMetadata::new(P::DEFAULT_FADE_TIME, RequiredRead, None, Always),
PropertyMetadata::new(P::DEFAULT_RAMP_RATE, RequiredRead, None, Always),
PropertyMetadata::new(P::DEFAULT_STEP_INCREMENT, RequiredRead, None, Always),
PropertyMetadata::new(P::MIN_PRES_VALUE, Optional, None, ReadOnly),
PropertyMetadata::new(P::MAX_PRES_VALUE, Optional, None, ReadOnly),
PropertyMetadata::new(P::TRANSITION, Optional, None, Always),
PropertyMetadata::new(P::PROPERTY_LIST, RequiredRead, None, ReadOnly),
];
pub(super) fn for_color_object(object: &ColorObject) -> Cow<'_, [PropertyMetadata]> {
with_optional(
COLOR_BASE,
object.value_source(),
object.audit_policy(),
object.profile(),
)
}
pub(super) fn for_color_temperature_object(
object: &ColorTemperatureObject,
) -> Cow<'_, [PropertyMetadata]> {
with_optional(
COLOR_TEMPERATURE_BASE,
object.value_source(),
object.audit_policy(),
object.profile(),
)
}
fn with_optional(
base: &'static [PropertyMetadata],
value_source: &SingleValueSource,
policy: &ObjectAuditPolicy,
profile: &ObjectProfile,
) -> Cow<'static, [PropertyMetadata]> {
let audit = (*policy != ObjectAuditPolicy::default()).then(|| policy.metadata());
let mut rows = value_source
.metadata()
.into_iter()
.chain(audit.into_iter().flatten())
.chain(profile.metadata())
.peekable();
if rows.peek().is_none() {
return Cow::Borrowed(base);
}
let (property_list, base) = base.split_last().expect("a Property_List row");
let mut metadata = base.to_vec();
metadata.extend(rows);
metadata.push(*property_list);
Cow::Owned(metadata)
}