use std::fmt::{self, Debug, Formatter};
use std::ops::{Range,Deref,Sub};
use std::cell::UnsafeCell;
use std::rc::Rc;
use ::{Property, StreamRc, PropertyT, IterAsync, Parameter, Stream, StreamT};
#[cfg(feature="glin")]
use glin as gl;
#[cfg(feature="numbers")]
use num_traits::{ToPrimitive,FromPrimitive};
use serde::{Serialize, Serializer};
use serde::ser::SerializeStruct;
#[derive(Clone,Debug,Copy,Serialize,Deserialize)]
pub enum Scale{
Linear,
Log,
}
#[derive(Clone,Debug,Serialize,Deserialize)]
pub struct RangedParameterMut<'a,T: Clone + Debug + 'static,R=T>{
property: Property<'a,T>,
scale: Scale,
range: Range<R>,
}
impl<'a,T:Clone + Debug, R:Clone> RangedParameterMut<'a,T,R>{
pub fn new(value: T, range: Range<R>) -> RangedParameterMut<'a,T,R>{
RangedParameterMut{
property: Property::new(value),
scale: Scale::Linear,
range: range,
}
}
pub fn new_log_scale(v: T, range: Range<R>) -> RangedParameterMut<'a,T,R>{
RangedParameterMut{
property: Property::new(v),
scale: Scale::Log,
range: range,
}
}
pub fn from_property(property: Property<'a, T>, range: Range<R>) -> RangedParameterMut<'a,T,R>{
RangedParameterMut{
property,
scale: Scale::Linear,
range: range,
}
}
pub fn from_property_log_scale(property: Property<'a, T>, range: Range<R>) -> RangedParameterMut<'a,T,R>{
RangedParameterMut{
property,
scale: Scale::Log,
range: range,
}
}
pub fn range(&self) -> Range<R>{
self.range.clone()
}
pub fn by_ref(&self) -> &RangedParameterMut<'a,T,R>{
self
}
#[inline]
pub fn min(&self) -> R{
self.range.start.clone()
}
#[inline]
pub fn max(&self) -> R{
self.range.end.clone()
}
pub fn to_value(&self) -> T{
self.property.to_value()
}
pub fn set(&mut self, t: T){
self.property.set(t)
}
pub fn scale(&self) -> Scale{
self.scale
}
pub fn into_property(self) -> Property<'a,T>{
self.property
}
pub fn stream(self) -> StreamRc<'a,T>{
self.property.stream()
}
pub fn map<'b,T2:Clone + Debug,F:FnMut(T)->T2 + 'a>(self, f: F) -> RangedParameterMut<'a,T2,R>{
RangedParameterMut{
property: self.property.map(f),
scale: self.scale,
range: self.range
}
}
}
impl<'a,T:Clone + Debug, R:Clone + Debug> RangedParameterMut<'a,T,R>{
pub fn to_const(self) -> RangedParameter<'a,T,R>{
RangedParameter::new(self.property.clone(), self.range)
}
}
impl<'a, T: Clone + Debug,R> PropertyT<'a,T> for RangedParameterMut<'a,T,R>{
fn iter_async<'b>(self) -> IterAsync<'b,T> where 'a: 'b{
self.property.iter_async()
}
fn to_parameter<'b>(self) -> Parameter<'b,T> where 'a: 'b{
self.property.to_parameter()
}
}
impl<'a, T: Clone + Debug + 'a, R: Sub<Output=R> + Clone + 'static> RangedParameterMut<'a, T,R>{
#[inline]
pub fn diff(&self) -> R{
self.max() - self.min()
}
}
#[cfg(feature="numbers")]
impl<'a, T: Sub<Output=T> + Clone + Debug + ToPrimitive + FromPrimitive + 'static, R:Clone + ToPrimitive + Sub<Output=R> + 'static> RangedParameterMut<'a, T,R>{
#[inline]
pub fn pct(&self) -> f64{
let pct = (self.to_f64().unwrap() - self.min().to_f64().unwrap()) / self.diff().to_f64().unwrap();
match self.scale{
Scale::Linear => pct,
Scale::Log => pct.sqrt(),
}
}
#[inline]
pub fn set_pct(&mut self, pct: f64){
let pct = match self.scale{
Scale::Linear => pct,
Scale::Log => pct * pct,
};
let v = pct * self.diff().to_f64().unwrap() + self.min().to_f64().unwrap();
self.set(T::from_f64(v).unwrap());
}
}
impl<'a, T: Clone + Debug + 'static, R> Deref for RangedParameterMut<'a,T,R>{
type Target = T;
fn deref(&self) -> &T{
self.property.deref()
}
}
#[cfg(feature="glin")]
impl<'a, T: gl::program::AsUniform<T> + Clone + Debug, R> gl::program::AsUniform<T> for RangedParameterMut<'a,T,R>{
fn as_uniform(&self) -> gl::program::UniformValue{
self.property.to_value().as_uniform()
}
}
pub struct IterParameter<'a, T>{
iter: Iter<'a, T>,
last_value: UnsafeCell<Option<T>>,
}
impl<'a, T: PartialEq> PartialEq for IterParameter<'a, T>{
fn eq(&self, other: &IterParameter<'a,T>) -> bool{
unsafe{ *self.last_value.get() == *other.last_value.get() }
}
}
impl<'a, T: Debug> Debug for IterParameter<'a,T>{
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
fmt.debug_struct("IterPara,eter")
.field("last_value", &self.last_value)
.finish()
}
}
impl<'a, T: Clone + Debug> IterParameter<'a,T>{
pub fn new<I: Iterator<Item=T> + 'a>(iter: I) -> IterParameter<'a,T>{
IterParameter{
iter: Iter{ iter: Rc::new(UnsafeCell::new(iter)) },
last_value: UnsafeCell::new(None),
}
}
#[inline]
fn update(&self){
let iter = unsafe{ &mut *self.iter.iter.get() };
if let Some(value) = iter.last() {
unsafe{ *self.last_value.get() = Some(value) }
}
}
pub fn iter(&self) -> Iter<'a,T>{
self.iter.clone()
}
}
#[derive(Clone)]
pub struct Iter<'a, T>{
iter: Rc<UnsafeCell<Iterator<Item=T> + 'a>>,
}
impl<'a,T> Iterator for Iter<'a,T>{
type Item = T;
fn next(&mut self) -> Option<T>{
unsafe{ (*self.iter.get()).next() }
}
}
pub trait ConstParameter<'a,T: Clone + Debug>: Debug{
fn to_value(&self) -> Option<T>;
fn as_value(&self) -> Option<&T>;
fn iter(&self) -> Iter<'a,T>;
}
impl<'a, T: Clone + Debug> ConstParameter<'a,T> for IterParameter<'a,T>{
fn to_value(&self) -> Option<T>{
self.update();
unsafe{ (*self.last_value.get()).clone() }
}
fn as_value(&self) -> Option<&T>{
self.update();
unsafe{ (*self.last_value.get()).as_ref() }
}
fn iter(&self) -> Iter<'a,T>{
(*self).iter()
}
}
impl<'a, T: Clone + Debug + 'a> ConstParameter<'a,T> for Property<'a,T>{
fn to_value(&self) -> Option<T>{
Some(self.to_value())
}
fn as_value(&self) -> Option<&T>{
Some(self.value())
}
fn iter(&self) -> Iter<'a,T>{
Iter{
iter: Rc::new(UnsafeCell::new(self.clone().iter_async()))
}
}
}
#[derive(Clone,Debug)]
pub struct RangedParameter<'a, T:Debug, R:Debug=T>{
param: Rc<ConstParameter<'a,T> + 'a>,
scale: Scale,
range: Range<R>,
}
impl<'a, T: Clone + Debug + 'a, R: Clone + Debug> RangedParameter<'a,T,R>{
pub fn from_iter<I: Iterator<Item=T> + 'a>(iter: I, range: Range<R>) -> RangedParameter<'a,T,R>{
RangedParameter{
param: Rc::new(IterParameter::new(iter)),
scale: Scale::Linear,
range: range
}
}
pub fn from_iter_log_scale<I: Iterator<Item=T> + 'a>(iter: I, range: Range<R>) -> RangedParameter<'a,T,R>{
RangedParameter{
param: Rc::new(IterParameter::new(iter)),
scale: Scale::Log,
range: range
}
}
pub fn new(property: Property<'a,T>, range: Range<R>) -> RangedParameter<'a,T,R>{
RangedParameter{
param: Rc::new(property),
scale: Scale::Linear,
range: range
}
}
pub fn new_log_scale(property: Property<'a,T>, range: Range<R>) -> RangedParameter<'a,T,R>{
RangedParameter{
param: Rc::new(property),
scale: Scale::Log,
range: range
}
}
pub fn range(&self) -> Range<R>{
self.range.clone()
}
pub fn by_ref(&self) -> &RangedParameter<'a,T,R>{
self
}
#[inline]
pub fn min(&self) -> R{
self.range.start.clone()
}
#[inline]
pub fn max(&self) -> R{
self.range.end.clone()
}
pub fn to_value(&self) -> Option<T>{
self.param.to_value()
}
pub fn as_value(&self) -> Option<&T>{
self.param.as_value()
}
pub fn iter(&self) -> Iter<'a,T>{
self.param.iter()
}
}
impl<'a, T: Clone + Debug + 'a, R: Sub<Output=R> + Clone + Debug + 'static> RangedParameter<'a, T, R>{
#[inline]
pub fn diff(&self) -> R{
self.max() - self.min()
}
}
#[cfg(feature="numbers")]
impl<'a, T, R> RangedParameter<'a, T,R>
where T: Sub<Output=T> + Clone + Debug + ToPrimitive + FromPrimitive + 'static,
R:Clone + ToPrimitive + Sub<Output=R> + Debug + 'static
{
#[inline]
pub fn pct(&self) -> Option<f64>{
self.to_value().map(|v| {
let pct = (v.to_f64().unwrap() - self.min().to_f64().unwrap()) / self.diff().to_f64().unwrap();
match self.scale{
Scale::Linear => pct,
Scale::Log => pct.sqrt(),
}
})
}
}
impl<'a, T: Clone + Debug + Serialize + 'a, R: Clone + Debug + Serialize> Serialize for RangedParameter<'a,T,R>{
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error>{
let mut state = serializer.serialize_struct("RangedParameter", 3)?;
state.serialize_field("param", &self.as_value())?;
state.serialize_field("scale", &self.scale)?;
state.serialize_field("range", &self.range)?;
state.end()
}
}
impl<'a, T: PartialEq + Clone + Debug + 'a, R: PartialEq + Clone + Debug> PartialEq for RangedParameter<'a,T,R>{
fn eq(&self, other: &RangedParameter<'a,T,R>) -> bool{
self.as_value() == other.as_value() &&
self.range() == other.range()
}
}
pub trait ConnectToParameter<'a,T: Clone + Debug + 'a,R>{
fn connect_to_ranged_parameter_pct(self, &mut RangedParameterMut<'a,T,R>) -> Stream<'a,T>;
}
#[cfg(feature="numbers")]
impl<'a,T: Clone + Debug + 'a + FromPrimitive + ToPrimitive, R: Sub<Output=R> + ToPrimitive + Clone + 'static> ConnectToParameter<'a,T,R> for Stream<'a,f64>{
fn connect_to_ranged_parameter_pct(self, param: &mut RangedParameterMut<'a,T,R>) -> Stream<'a,T>{
let param = param.clone();
let mut property = param.property.clone();
self.map(move |pct| {
let pct = match param.scale(){
Scale::Linear => pct,
Scale::Log => pct * pct,
};
let v = pct * param.diff().to_f64().unwrap() + param.min().to_f64().unwrap();
T::from_f64(v).unwrap()
})
.connect_to_property(&mut property)
}
}