{-# LANGUAGE DataKinds #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeFamilies #-}

{-# LANGUAGE NoIncoherentInstances #-}
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE NoUndecidableInstances #-}

module Vivid.UGens.Buffer (

     -- * Buffer > Info

     bufChannels
   , bufDur
   , bufFrames
   , bufRateScale
   , bufSampleRate
   , bufSamples

     -- * Buffer

   , bufRd
   , bufWr
---   , dbufrd
---   , dbufwr
---   , delTapRd
---   , delTapWr
---   , detectIndex
     -- In Vivid.UGens.InOut:
   -- , diskIn
     -- In Vivid.UGens.InOut:
   -- , diskOut
     -- In Vivid.UGens.Generators.Granular:
   -- , grainBuf
---   , harmonics
---   , index
---   , indexInBetween
---   , indexL
   , localBuf
---   , multiTap
   , phasor
   , playBuf
   , recordBuf
---   , scopeOut
---   , shaper
     -- In Vivid.UGens.Generators.Granular
   -- , tGrains
---   , tap
     -- In Vivid.UGens.InOut:
   -- , vDiskIn
     -- In Vivid.UGens.Generators.Granular
   -- , warp1
---   , wrapIndex
   ) where

import Vivid.SynthDef
import Vivid.SynthDef.FromUA
import Vivid.UGens.Args

import Data.Proxy

-- | Add a single LocalBuf for FFT
-- 
--   Can use 'Vivid.UGens.Args.chans_' for \"numChans\"
--   and 'frames_' for \"Vivid.UGens.Args.numFrames\"
localBuf :: Args '["numChans","numFrames"] '[] a => a -> SDBody a Signal
localBuf args = do
   mlb <- addUGen $ UGen (UGName_S "MaxLocalBufs") IR [Constant 1] 1
   numChannels' <- uaArgVal args (Proxy::Proxy "numChans")
   numFrames' <- uaArgVal args (Proxy::Proxy "numFrames")
   -- Another example where the args in sclang and scsynth are in different orders:
   addUGen $ UGen (UGName_S "LocalBuf") IR [numChannels', numFrames', mlb] 1


-- | Unlike in SC, "doneAction" defaults to 2
playBuf :: (Args '["buf"] '["rate","trigger","startPos","loop","doneAction"] a) => a -> SDBody a Signal
playBuf = makeUGen
   "PlayBuf" AR
   (Vs::Vs '["buf","rate","trigger","startPos","loop","doneAction"])
   (rate_ ((1)::Float), trigger_ ((1)::Float), startPos_ ((0)::Float)
   ,loop_ ((0)::Float), doneAction_ ((2)::Float))


-- | Unlike in SC, "doneAction" defaults to 2 and "loop" defaults to 0
recordBuf :: (Args '["buf","in"] '["offset","recLevel","preLevel","run","loop","trigger","doneAction"] a) => a -> SDBody a Signal
recordBuf = makeUGen
   "RecordBuf" AR
   (Vs::Vs '["buf","offset","recLevel","preLevel","run","loop","trigger","doneAction","in"])
   -- this is another example of different order:
   (offset_ ((0)::Float), recLevel_ ((1)::Float), preLevel_ ((0)::Float), run_ ((1)::Float), loop_ ((0)::Float), trigger_ ((1)::Float), doneAction_ ((2)::Float))

-- | Defaults to 'KR'. Can be 'IR' too but it's not recommended.
bufChannels :: (Args '["buf"] '[] a) => a -> SDBody a Signal
bufChannels = makeUGen
   "BufChannels" KR
   (Vs::Vs '["buf"])
   NoDefaults

-- | Defaults to 'KR'. Can be 'IR' too but it's not recommended.
bufDur :: (Args '["buf"] '[] a) => a -> SDBody a Signal
bufDur = makeUGen
   "BufDur" KR
   (Vs::Vs '["buf"])
   NoDefaults

-- bufFrames :: (Args '["buf"] '[] a) => a -> SDBody a Signal

-- | Defaults to 'KR'. Can be 'IR' too but it's not recommended.
-- 
--   Note you don't need to use "buf_" when you use this
bufFrames :: ToSig s as => s -> SDBody' as Signal
bufFrames = (flip (.)) buf_ $ makeUGen
   "BufFrames" KR
   (Vs::Vs '["buf"])
   NoDefaults

-- bufRateScale :: (Args '["buf"] '[] a) => a -> SDBody a Signal

-- | Defaults to 'KR'. Can be 'IR' too but it's not recommended.
-- 
--   Note you don't need to use "buf_" when you use this
bufRateScale :: ToSig s as => s -> SDBody' as Signal
bufRateScale = (flip (.)) buf_ $ makeUGen
   "BufRateScale" KR
   (Vs::Vs '["buf"])
   NoDefaults

-- bufSampleRate :: (Args '["buf"] '[] a) => a -> SDBody a Signal

-- | Defaults to 'KR'. Can be 'IR' too but it's not recommended.
-- 
--   Note you don't need to use "buf_" when you use this
bufSampleRate :: ToSig s as => s -> SDBody' as Signal
bufSampleRate = (flip (.)) buf_ $ makeUGen
   "BufSampleRate" KR
   (Vs::Vs '["buf"])
   NoDefaults

-- bufSamples :: (Args '["buf"] '[] a) => a -> SDBody a Signal

-- | Defaults to 'KR'. Can be 'IR' too but it's not recommended.
-- 
--   Note you don't need to use "buf_" when you use this
bufSamples :: ToSig s as => s -> SDBody' as Signal
bufSamples = (flip (.)) buf_ $ makeUGen
   "BufSamples" KR
   (Vs::Vs '["buf"])
   NoDefaults

-- | "phase" must be at audio rate ('AR')
bufRd :: (Args '[{- "numChans",-} "buf", "phase"] '["loop", "interp"] a) => a -> SDBody a Signal
bufRd = makeUGen
   "BufRd" AR
   (Vs::Vs '[{- "numChans", -} "buf", "phase", "loop", "interp"])
   (loop_ ((1)::Float), interp_ ((2)::Float))

-- | "phase" must be at audio rate ('AR')
bufWr :: (Args '["in", {- "numChans", -} "buf", "phase"] '["loop"] a) => a -> SDBody a Signal
bufWr = makeUGen
   "BufWr" AR
   -- An example of arguments in different orders in sclang and scsynth:
   (Vs::Vs '["buf", "phase", "loop", "in"])
   (loop_ ((1)::Float))

        -- returns demandrate
--- dbufrd ::
--- dbufrd =
--- dbufwr ::
--- dbufwr =

-- | "phase" must be the output of 'delTapWr'
--delTapRd :: (Args '["buf", "phase", "delSecs"] '["interp"] a) => s -> SDBody a Signal
--- delTapRd ::
--- delTapRd =

--- delTapWr ::
--- delTapWr =
--- detectIndex ::
--- detectIndex =
--- harmonics ::
--- harmonics =
--- index ::
--- index =
--- indexInBetween ::
--- indexInBetween =
--- indexL ::
--- indexL =
--- multiTap ::
--- multiTap =

phasor :: (Args '[] '["trigger", "rate", "start", "end", "resetPos"] a) => a -> SDBody a Signal
phasor = makeUGen
   "Phasor" AR
   (Vs::Vs '["trigger", "rate", "start", "end", "resetPos"])
   (trig_ ((0)::Float), rate_ ((1)::Float), start_ ((0)::Float), end_ ((1)::Float), resetPos_ ((0)::Float))

--- scopeOut ::
--- scopeOut =
--- shaper ::
--- shaper =
--- tap ::
--- tap =
--- wrapIndex ::
--- wrapIndex =