module Data.MovingAverage.Simple
    ( simple
    ) where

import Data.MovingAverage.Types (SmoothedResults, MovingAverageError(..), buildSimpleMovingAverage)

simple :: Floating a => Int -> [a] -> Either MovingAverageError (SmoothedResults a)
simple _ [] = Left NoValuesProvided
simple n xs
  | n <= 0 = Left $ InvalidWindow "Window must be greater than 0"
  | otherwise =
        Right $ buildSimpleMovingAverage n xsAndSmoothedPairs
      where
        xsAndSmoothedPairs = zip xs (map fst3 $ scanl1 average sampleTriples)
        divisors = map fromIntegral $ [1..n] ++ repeat n
        nAgos = replicate (n - 1) 0 ++ xs
        sampleTriples = zip3 xs divisors nAgos

average :: Fractional a => (a, a, a) -> (a, a, a) -> (a, a, a)
average (prevAvg, prevDiv, dropMe) (sample, divisor, nAgo) =
    (newAvg, divisor, nAgo)
  where
    prevSum = prevAvg * prevDiv
    newAvg = (prevSum + sample - dropMe) / divisor

fst3 :: (a, b, c) -> a
fst3 (x, _, _) = x