{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, FlexibleContexts #-}
-- | Special case of "Temporal.Media". Time is @Double@
module Temporal.Media.Double (
	-- * Time classes
	Dur, none, dur, stretch, ToMaybe(..), 
    tmap, dmap, tdmap, 
    sustain, sustainBy,
    tstretch, 
    -- * Transformers
	Reversible(..), slice, take, drop, cut, 
	-- * Structure 
	Construct(..), Arrangeable(..), Controlable(..),
	sequent, parallel, loop, delay, temp,
	-- * Media
	Media(..), fold, fromMedia,
	-- * Simple interperetation
	-- ** Event list
	Event, EventList(..), 
	mapEvent, toEvent, toEventList,
	-- ** Unit Media
	MediaUnit(..), unMediaUnit, foldU, fromMediaUnit,
	Unit(..),
    -- * Misc
    tmapRel, dmapRel, tdmapRel, tstretchRel, linseg
) 
where

import Prelude hiding (take, drop, reverse)
import Control.Applicative

import qualified Temporal.Media as M
import Temporal.Media (
	ToMaybe(..),
	Reversible(..), 
	Construct(..), Arrangeable(..), Controlable(..), 
	sequent, parallel, loop,
	Media(..), fold, fromMedia, linseg)

----------------------------------------
-- Time 
--

type Time = Double
type Dur  = Double

none :: M.Temporal Dur a => Dur -> a
none = M.none

dur :: M.Temporal Dur a => a -> Dur
dur = M.dur

stretch :: M.Stretchable Dur a => Dur -> a -> a
stretch = M.stretch

-- | temporal stretch
tstretch :: M.TemporalStretchable Dur a => (Time -> Dur) -> a -> a
tstretch = M.tstretch

tstretchRel :: M.TemporalStretchable Dur a => (Time -> Dur) -> a -> a
tstretchRel = M.tstretchRel

tmap :: M.TemporalFunctor Dur f => (Time -> a -> b) -> (f a -> f b)
tmap = M.tmap

dmap :: M.TemporalFunctor Dur f => (Dur -> a -> b) -> (f a -> f b)
dmap = M.dmap

tdmap :: M.TemporalFunctor Dur f => (Time -> Dur -> a -> b) -> (f a -> f b)
tdmap = M.tdmap


tmapRel :: (M.Temporal Dur (f a), M.TemporalFunctor Dur f) => (Time -> a -> b) -> (f a -> f b)
tmapRel = M.tmapRel

dmapRel :: (M.Temporal Dur (f a), M.TemporalFunctor Dur f) => (Dur -> a -> b) -> (f a -> f b)
dmapRel = M.dmapRel

tdmapRel :: (M.Temporal Dur (f a), M.TemporalFunctor Dur f) => (Time -> Dur -> a -> b) -> (f a -> f b)
tdmapRel = M.tdmapRel

sustain :: M.Sustainable Dur f => Dur -> f a -> f a
sustain = M.sustain

sustainBy :: M.Sustainable Dur f => (Dur -> Dur -> a -> (b, Dur)) -> f a -> f b
sustainBy = M.sustainBy

--------------------------------------------
-- transformers

slice :: M.Sliceable Dur a => Dur -> Dur -> a -> a
slice = M.slice

take :: M.Sliceable Dur a => Dur -> a -> a
take = M.take

drop :: M.Sliceable Dur a => Dur -> a -> a
drop = M.drop

cut :: (Reversible a, M.Sliceable Dur a) => Dur -> Dur -> a -> a
cut = M.cut

--------------------------------------------
-- Structure

delay :: (M.Temporal Dur a, Arrangeable a) => Dur -> a -> a
delay = M.delay

temp :: (Construct m, M.Temporal Dur (m a), M.Stretchable Dur (m a)) 
	=> Dur -> a -> m a
temp = M.temp
	

-------------------------------------------- 
-- EventList

type Event a     = M.Event Dur a
type EventList a = M.EventList Dur a

mapEvent :: (a -> b) -> Event a -> Event b
mapEvent = M.mapEvent

toEvent :: (M.Temporal Dur (m a), ToMaybe m) => m a -> EventList a
toEvent = M.toEvent

toEventList :: (M.Temporal Dur (m a), ToMaybe m) 
	=> (c -> EventList a -> EventList a) 
	-> Media c (m a) -> EventList a
toEventList = M.toEventList

--------------------------------------------
-- MediaUnit

type MediaUnit c a = M.MediaUnit Dur c a

unMediaUnit :: MediaUnit c a -> Media c (Unit a)
unMediaUnit = M.unMediaUnit

foldU :: (Dur -> a -> b) -> (b -> b -> b) -> (b -> b -> b) -> (c -> b -> b)
	-> MediaUnit c a -> Maybe b
foldU = M.foldU

fromMediaUnit :: (c -> EventList a -> EventList a) -> MediaUnit c a -> EventList a
fromMediaUnit = M.fromMediaUnit

--------------------------------------------
-- Temp

type Unit a = M.Unit Dur a