module Todo (getTodos
            ,updateTask
            ,deleteTodo
            ,qetTasks'
            ,makeQuery'
            ,conv'
            ,convRow'
            ,genModal'
            ) where

import Database
import Data.List.Split
import Control.Monad.IO.Class
import Data.Time
import Data.List.Split as S
import Paths_Villefort
import Database.HDBC.Sqlite3 
import Database.HDBC


data Row = Row { rid :: Int,
                 title :: String,
                 description :: String,
                 due :: String,
                 time :: Int
               } deriving (Show)

--toRow :: Maybe [String] -> Maybe Row
toRow x =  Row (read (x !! 0) :: Int) (x !! 1) (x !! 2) (x !! 3) (read( x !! 4) :: Int)

qetTasks' = do
  -- I would like to take this moment to personally apoligize to the sql gods for creating this monstrosity.
  x <- makeQuery' "select id, Title, Description, Due,  sum(time) from todo where state=1 group by id "
  return (map toRow x)

convRow' dat = Prelude.map (\x -> Prelude.map (\y -> conv' y ) x) dat

--conv :: SqlValue -> String
conv' x = case fromSql x of
  Just x -> fromSql x :: String
  Nothing -> "1"


--makeQuery :: Query -> IO [[String]]
makeQuery' query = do
  conn <- getDb
  taskRaw <- quickQuery' conn query []
  disconnect conn
  return (convRow' taskRaw)


merge [] ys = ys
merge (x:xs) ys = x:merge ys xs


  
genModal' row = if rid row == 1 then return (" ") else do
  let f = due row
  modal <- getModal
  days  <- daysTilDue f
  let da = [daysToColor' days ,
            show $ rid row,
            (convTitle $ title row) ++ "Due in " ++  show days,
            show $ rid row,
            title row,
            description row,
            show $ time row,
            "/delete",
            show $ rid row
           ]

  return $ mconcat $  merge modal da
 

--genModal row =

daysToColor' x = if x < 1 then "btn-due0"
            else if x == 1 then "btn-due1"
            else if x == 2 then "btn-due2"
            else if x == 3 then "btn-due3"
            else if x == 4 then "btn-due4"
            else if x == 5 then "btn-due5"
            else if x == 6 then "btn-due6"
            else "btn-due7"




convTitle title
  | length s1 > 30 = s1
  | length s2 > 30 = s2
  | length s3 > 30 = s3
  | length s4 > 30 = s4
  | otherwise = title
  where split = (Data.List.Split.splitOn "." title)
        s1 = (split !! 0)
        s2 = mconcat (take 2 split)
        s3 = mconcat (take 3 split)
        s4 = mconcat (take 4 split)
          

getModal :: IO [[Char]]
--getModal =  path >>= \path -> readFile (path ++ "templates/modal.ts") >>= \rawModal -> return  (Data.List.Split.splitOn "}" rawModal)
getModal =  getDataFileName "templates/modal.ts" >>= \path -> readFile path>>= \rawModal -> return  (Data.List.Split.splitOn "}" rawModal)

daysTilDue date = do
  c <- getCurrentTime
  let (y,m,d) = toGregorian $ utctDay c
  let split = Data.List.Split.splitOn "-" date
  current <- fromZonedTimeToDay <$> show <$> getZonedTime
  let due     = fromGregorian (read (split !! 0) :: Integer) (read (split !! 1) :: Int) (read (split !! 2) :: Int)
  return $ (diffDays  due current) 

fromZonedTimeToDay x = fromGregorian (read (nums !! 0) :: Integer) (read (nums !! 1) :: Int) (read (nums !! 2) :: Int) 
  where nums = S.splitOn "-" $  take 10 x
  
-- | Returns html from todos 
getTodos = do
  tasks <-  qetTasks'
  do liftIO $ putStrLn $ show tasks
  path  <- path 
  modals <- sequence $  genModal' <$>  tasks
  headerPath <- getDataFileName "templates/header"
  header <- liftIO $ readFile headerPath
  let body = Prelude.concat modals
  return (header ++  body)

-- | Delete a done task from database sets state = 0 but it's record is still maintained in the database for the stats page.
deleteTodo raw = do
    let da   = Data.List.Split.splitOn "&" (show raw)
    let rawid = Data.List.Split.splitOn "=" $  (Prelude.init (da !! 1))
    let id   = read (rawid!! 1) :: Int
    let rawtime = Data.List.Split.splitOn "=" $ (da !! 0)
    let time = read (rawtime !! 1) :: Int
    do liftIO $ delTask id 
    do liftIO $ addTime id time
    return ()


addTime :: Int -> Int -> IO ()
addTime id time = execQuery "update todo set time = ? where id = ?" [time,id]
  
delTask :: Int ->  IO ()
delTask id = execQuery "update todo  set state = 0 where id = ?" [id]

updateTask :: Int -> Int ->  IO ()
updateTask id time = execQuery "insert into todo (id,Description,Title,Entered,Due,state,time,Subject) select id,Description,Title,Entered,Due,1,?,Subject from todo where id = ? limit 1" [ time, id]