module EventLoop.Output.Single (outSingle) where

import qualified Network.Socket     as S
import qualified Network.WebSockets as WS
import qualified Data.Text          as T

import EventLoop.EventProcessor (sendResponse, IOMessage)
import EventLoop.Output.OutputEvent
import EventLoop.Output.Graphical
import EventLoop.Output.SystemMessage
import EventLoop.Config
import EventLoop.Json
import EventLoop.CommonTypes

outSingle :: OutputEvent -> IO ()
outSingle out = S.withSocketsDo $ do
                                    sock <- WS.makeSocket ipadres (fromIntegral port)
                                    pendingConn <- WS.makePendingConnection sock
                                    conn <- WS.acceptRequest pendingConn
                                    sendResponse conn setup
                                    sendResponse conn out'
                                    sendResponse conn close
                                    WS.sendClose conn (T.pack "")
                                    WS.closeSocket sock
                                    return ()
                where
                    setup = toIOMessage (setupMessage out)
                    out' = toIOMessage out 
                    close = toIOMessage closeMessage
    
setupMessage :: OutputEvent -> OutputEvent
setupMessage (OutGraphical (Draw g _)) = OutSysMessage [CanvasSetup dim]
                                    where
                                        dim = maxDimensions g
setupMessage _ = OutSysMessage [CanvasSetup (512, 512)]                                        

closeMessage :: OutputEvent
closeMessage = OutSysMessage [Close]
    
toIOMessage :: OutputEvent -> IOMessage
toIOMessage = toJsonMessage

maxDimensions :: GObject -> Dimension
maxDimensions (GObject _ prim [])     = maxDimensionsPrim prim
maxDimensions (GObject n prim (c:cs)) = (max h h', max w w')
                                        where
                                            (h, w) = maxDimensions c
                                            (h', w') = maxDimensions (GObject n prim cs)
maxDimensions (Container [])          = (0, 0)
maxDimensions (Container (c:cs))      = (max h h', max w w')
                                        where
                                            (h, w) = maxDimensions c
                                            (h', w') = maxDimensions (Container cs)

maxDimensionsPrim :: Primitive -> Dimension
maxDimensionsPrim (Text _ _ _ (x, y) size _ str fromCenter) | fromCenter = (y + size / 2, x + (fromIntegral $ length str * 10) / 2)
                                                            | otherwise  = (y + size, x + (fromIntegral $ length str * 10))
maxDimensionsPrim (Line _ _ [])                             = (0, 0)                                                                    
maxDimensionsPrim (Line _ _ [(x, y)])                       = (y, x)
maxDimensionsPrim (Line ec et ((x, y):xs))                  = (max y y', max x x')
                                                        where
                                                            (y', x') = maxDimensionsPrim (Line ec et xs) 
maxDimensionsPrim (Rect _ _ _ (x, y) (h, w))                = (y + h / 2, x + w / 2) 
maxDimensionsPrim (Arc _ _ _ (x, y) r _ _)                  = (y + r, x + r)