module FuzzyTimings.Schedule (scheduleTimings) where
import FuzzyTimings.TimingBuckets
import FuzzyTimings.TimeSlice
import FuzzyTimings.SlicedTime
import FuzzyTimings.AccTiming
import FuzzyTimings.FuzzyTiming
import qualified Data.Map as Map
import System.Random
import Data.List

scheduleTimings :: Show k =>  SlicedTime (FuzzyCountMap k) -> IO [AccTiming k]
scheduleTimings st = do
    accTimings <- mapM scheduleSlice $ toTimeSlices st
    return $ concat accTimings

scheduleSlice :: Show k => TimeSlice (FuzzyCountMap k) -> IO [AccTiming k]
scheduleSlice ts = do
    print instanceRanges
    instances <- mapM rndInstancePos instanceRanges
    return [ AccTiming (ftId ft) (addSecs pos (tsStart ts)) (ftDuration ft)
           | (ft,pos) <- schedule instances ]
    where
        schedule instances = let 
            sortedInstances = sortBy (\(_,pos1) (_,pos2) -> compare pos1 pos2)
                                     instances
            in scheduleInstances 0 [ (ft,pos i (length instances)) 
                                   | ((ft,_), i) <- zip sortedInstances [0..] ]
        instanceRanges = [ (ft,pos (i-1) ttp, (pos (i-1) ttp + pos i ttp) `div` 2)  
                         | (ft,ttp) <- fts, i <- [1..ttp] ]
        pos i ttp = (tsDuration ts * i) `div` ttp
        fts = [ (ft,floor ttp) | (ft,ttp) <- Map.toList (tsValue ts) ]
        rndInstancePos (ft,start,end) = do
            pos <- randomRIO (start,end)
            return (ft,pos)

        
scheduleInstances :: Int -> [(FuzzyTiming k, Int)] -> [(FuzzyTiming k, Int)]
scheduleInstances now ((ft,pos):xs) 
    | now > pos = (ft,now):scheduleInstances (now+ftDuration ft) xs
    | otherwise = (ft,pos):scheduleInstances (pos+ftDuration ft) xs
scheduleInstances _ [] = []