use std::collections::VecDeque;
use std::marker::PhantomData;
#[derive(Clone, Debug, PartialEq, Eq, Copy)]
pub struct Quad<T> {
    
    pub x: T,
    
    pub y: T,
    
    pub z: T,
    
    pub w: T,
}
impl<T> Quad<T> {
    
    pub fn new(v0: T, v1: T, v2: T, v3: T) -> Self {
        Quad {
            x: v0,
            y: v1,
            z: v2,
            w: v3,
        }
    }
}
#[derive(Clone, Debug, PartialEq, Eq, Copy)]
pub struct Triangle<T> {
    
    pub x: T,
    
    pub y: T,
    
    pub z: T,
}
impl<T> Triangle<T> {
    
    pub fn new(v0: T, v1: T, v2: T) -> Self {
        Triangle {
            x: v0,
            y: v1,
            z: v2,
        }
    }
}
#[derive(Debug, Clone, PartialEq, Copy)]
pub enum Polygon<T> {
    
    PolyTri(Triangle<T>),
    
    PolyQuad(Quad<T>),
}
pub trait EmitVertices<T> {
    
    
    
    fn emit_vertices<F>(self, F)
    where
        F: FnMut(T);
}
impl<T> EmitVertices<T> for Line<T> {
    fn emit_vertices<F>(self, mut emit: F)
    where
        F: FnMut(T),
    {
        let Line { x, y } = self;
        emit(x);
        emit(y);
    }
}
impl<T> EmitVertices<T> for Triangle<T> {
    fn emit_vertices<F>(self, mut emit: F)
    where
        F: FnMut(T),
    {
        let Triangle { x, y, z } = self;
        emit(x);
        emit(y);
        emit(z);
    }
}
impl<T> EmitVertices<T> for Quad<T> {
    fn emit_vertices<F>(self, mut emit: F)
    where
        F: FnMut(T),
    {
        let Quad { x, y, z, w } = self;
        emit(x);
        emit(y);
        emit(z);
        emit(w);
    }
}
impl<T> EmitVertices<T> for Polygon<T> {
    fn emit_vertices<F>(self, emit: F)
    where
        F: FnMut(T),
    {
        use self::Polygon::{PolyQuad, PolyTri};
        match self {
            PolyTri(p) => p.emit_vertices(emit),
            PolyQuad(p) => p.emit_vertices(emit),
        }
    }
}
pub trait Vertices<SRC, V> {
    
    fn vertices(self) -> VerticesIterator<SRC, V>;
}
impl<V, P: EmitVertices<V>, T: Iterator<Item = P>> Vertices<T, V> for T {
    fn vertices(self) -> VerticesIterator<T, V> {
        VerticesIterator {
            source: self,
            buffer: VecDeque::new(),
        }
    }
}
pub struct VerticesIterator<SRC, V> {
    source: SRC,
    buffer: VecDeque<V>,
}
impl<V, U: EmitVertices<V>, SRC: Iterator<Item = U>> Iterator for VerticesIterator<SRC, V> {
    type Item = V;
    fn next(&mut self) -> Option<V> {
        loop {
            match self.buffer.pop_front() {
                Some(v) => return Some(v),
                None => (),
            }
            match self.source.next() {
                Some(p) => p.emit_vertices(|v| self.buffer.push_back(v)),
                None => return None,
            }
        }
    }
}
pub trait MapVertex<T, U> {
    
    
    type Output;
    
    fn map_vertex<F>(self, F) -> Self::Output
    where
        F: FnMut(T) -> U;
}
impl<T: Clone, U> MapVertex<T, U> for Line<T> {
    type Output = Line<U>;
    fn map_vertex<F>(self, mut map: F) -> Line<U>
    where
        F: FnMut(T) -> U,
    {
        let Line { x, y } = self;
        Line {
            x: map(x),
            y: map(y),
        }
    }
}
impl<T: Clone, U> MapVertex<T, U> for Triangle<T> {
    type Output = Triangle<U>;
    fn map_vertex<F>(self, mut map: F) -> Triangle<U>
    where
        F: FnMut(T) -> U,
    {
        let Triangle { x, y, z } = self;
        Triangle {
            x: map(x),
            y: map(y),
            z: map(z),
        }
    }
}
impl<T: Clone, U> MapVertex<T, U> for Quad<T> {
    type Output = Quad<U>;
    fn map_vertex<F>(self, mut map: F) -> Quad<U>
    where
        F: FnMut(T) -> U,
    {
        let Quad { x, y, z, w } = self;
        Quad {
            x: map(x),
            y: map(y),
            z: map(z),
            w: map(w),
        }
    }
}
impl<T: Clone, U> MapVertex<T, U> for Polygon<T> {
    type Output = Polygon<U>;
    fn map_vertex<F>(self, map: F) -> Polygon<U>
    where
        F: FnMut(T) -> U,
    {
        use self::Polygon::{PolyQuad, PolyTri};
        match self {
            PolyTri(p) => PolyTri(p.map_vertex(map)),
            PolyQuad(p) => PolyQuad(p.map_vertex(map)),
        }
    }
}
pub trait MapToVertices<T, U>: Sized {
    
    
    type Output;
    
    
    fn vertex<F>(self, map: F) -> MapToVerticesIter<Self, T, U, F>
    where
        F: FnMut(T) -> U;
}
impl<VIn, VOut, P, POut: MapVertex<VIn, VOut, Output = P>, T: Iterator<Item = POut>>
    MapToVertices<VIn, VOut> for T
{
    type Output = P;
    fn vertex<F>(self, map: F) -> MapToVerticesIter<T, VIn, VOut, F>
    where
        F: FnMut(VIn) -> VOut,
    {
        MapToVerticesIter {
            src: self,
            f: map,
            phantom: PhantomData,
        }
    }
}
pub struct MapToVerticesIter<SRC, T, U, F: FnMut(T) -> U> {
    src: SRC,
    f: F,
    phantom: PhantomData<(T, U)>,
}
impl<
        'a,
        P,
        POut: MapVertex<T, U, Output = P>,
        SRC: Iterator<Item = POut>,
        T,
        U,
        F: FnMut(T) -> U,
    > Iterator for MapToVerticesIter<SRC, T, U, F>
{
    type Item = P;
    fn size_hint(&self) -> (usize, Option<usize>) {
        self.src.size_hint()
    }
    fn next(&mut self) -> Option<P> {
        self.src.next().map(|x| x.map_vertex(|x| (self.f)(x)))
    }
}
#[derive(Clone, Debug, PartialEq, Eq, Copy, Hash)]
pub struct Line<T> {
    
    pub x: T,
    
    pub y: T,
}
impl<T> Line<T> {
    
    pub fn new(x: T, y: T) -> Self {
        Line { x: x, y: y }
    }
}
pub trait EmitLines {
    
    type Vertex;
    
    
    
    fn emit_lines<E>(self, emit: E)
    where
        E: FnMut(Line<Self::Vertex>);
}
impl<T: Clone> EmitLines for Triangle<T> {
    type Vertex = T;
    fn emit_lines<E>(self, mut emit: E)
    where
        E: FnMut(Line<T>),
    {
        emit(Line::new(self.x.clone(), self.y.clone()));
        emit(Line::new(self.y, self.z.clone()));
        emit(Line::new(self.z, self.x));
    }
}
impl<T: Clone> EmitLines for Quad<T> {
    type Vertex = T;
    fn emit_lines<E>(self, mut emit: E)
    where
        E: FnMut(Line<T>),
    {
        emit(Line::new(self.x.clone(), self.y.clone()));
        emit(Line::new(self.y, self.z.clone()));
        emit(Line::new(self.z, self.w.clone()));
        emit(Line::new(self.w, self.x));
    }
}
impl<T: Clone> EmitLines for Polygon<T> {
    type Vertex = T;
    fn emit_lines<E>(self, emit: E)
    where
        E: FnMut(Line<T>),
    {
        match self {
            Polygon::PolyTri(x) => x.emit_lines(emit),
            Polygon::PolyQuad(x) => x.emit_lines(emit),
        }
    }
}
pub trait Lines: Sized {
    
    type Vertex;
    
    fn lines(self) -> LinesIterator<Self, Self::Vertex>;
}
impl<T, P, V> Lines for T
where
    T: Iterator<Item = P>,
    P: EmitLines<Vertex = V>,
{
    type Vertex = V;
    fn lines(self) -> LinesIterator<T, V> {
        LinesIterator {
            source: self,
            buffer: VecDeque::new(),
        }
    }
}
pub struct LinesIterator<I, V> {
    source: I,
    buffer: VecDeque<Line<V>>,
}
impl<I, P, V> Iterator for LinesIterator<I, V>
where
    I: Iterator<Item = P>,
    P: EmitLines<Vertex = V>,
{
    type Item = Line<V>;
    fn size_hint(&self) -> (usize, Option<usize>) {
        let (n, _) = self.source.size_hint();
        (n, None)
    }
    fn next(&mut self) -> Option<Line<V>> {
        loop {
            match self.buffer.pop_front() {
                Some(v) => return Some(v),
                None => (),
            }
            match self.source.next() {
                Some(p) => p.emit_lines(|v| self.buffer.push_back(v)),
                None => return None,
            }
        }
    }
}