{-# LANGUAGE PatternGuards #-}
module FPPrac.GUI.Panel
  ( PanelItemType(..)
  , PanelContent
  , PanelItem
  , drawPanel
  , onItem
  , toggleItem
  , createDefState
  )
where

import Graphics.Gloss
import Graphics.Gloss.Data.Point

titleshift :: Float
titleshift     = 4

titlebarheight :: Float
titlebarheight = 16

titlebarShift :: Float
titlebarShift  = 8

lblVshift :: Float
lblVshift      = -6

data PanelItemType      = CheckButton | Button
  deriving (Eq,Show)

-- | (Id, Title, Type, x-coord, y-coord, width, height)
type PanelItem     = (Int,String,PanelItemType,Float,Float,Float,Float)

-- | (Title, width, height, menuItems, commandItems)
--
-- Note:
-- - panels are drawn in the center of the screen
--
-- - menu items are currently not supported
type PanelContent  = (String
                     ,Float, Float
                     ,[(String,[(String,Int)])]
                     ,[PanelItem]
                     )

createDefState ::
  PanelContent
  -> [(Int,String)]
createDefState (_, _, _, _, items) = map createDefStateItem items

createDefStateItem ::
  PanelItem
  -> (Int,String)
createDefStateItem (i,_,CheckButton,_,_,_,_)   = (i,"N")
createDefStateItem (i,_,_            ,_,_,_,_) = (i,"" )

drawPanel ::
  PanelContent
  -> [(Int,String)]
  -> Picture
drawPanel (title, w, h, _, items) itemStates
  = Pictures $
  [ Translate 0 titlebarShift $ Color white $ rectangleSolid w (h + titlebarheight)
  , Translate 0 titlebarShift $ Color black $ rectangleWire  w (h + titlebarheight)
  , drawTitleBar w h title
  ] ++ zipWith (drawItem w h) items itemStates

drawTitleBar ::
  Float
  -> Float
  -> String
  -> Picture
drawTitleBar w h title
  = Pictures
  [ Color black $ Line [(negate w/2, h/2), (w/2,h/2)]
  , Translate ((negate w/2)+5) (h/2 + titleshift) $ Color black $ Scale 0.1 0.1 $ Text title
  ]

drawItem ::
  Float
  -> Float
  -> PanelItem
  -> (Int, String)
  -> Picture
drawItem bboxW bboxH (_, name, CheckButton, x, y, w, h) (_,itemState)
  | x < (bboxW / 2)
  , x > (negate bboxW / 2 )
  , (y - titlebarheight) < (bboxH / 2)
  , (y - titlebarheight) > (negate bboxH / 2)
  , (x + w) < (bboxW / 2)
  , ((y - titlebarheight) + h) < (bboxH / 2)
  = Pictures $
  [ Translate x     (y - titlebarShift) $ Color black $ rectangleWire w h
  , Translate (x+w) (y - titlebarShift + lblVshift) $ Color black $ Scale 0.1 0.1 $ Text name
  ] ++ if (itemState == "Y") then
    [Translate 0 (-titlebarShift) $ Color black $ Line [(x-w/2,y-h/2),(x+w/2,y+h/2)]
    ,Translate 0 (-titlebarShift) $ Color black $ Line [(x-w/2,y+h/2),(x+w/2,y-h/2)]
    ]
    else []

  | otherwise
  = Blank

drawItem bboxW bboxH (_, name, Button, x, y, w, h) _
  | x < (bboxW / 2)
  , x > (negate bboxW / 2 )
  , (y - titlebarheight) < (bboxH / 2)
  , (y - titlebarheight) > (negate bboxH / 2)
  , (x + w) < (bboxW / 2)
  , ((y - titlebarheight) + h) < (bboxH / 2)
  = Pictures
  [ Translate x      (y - titlebarShift) $ Color black $ rectangleWire w h
  , Translate xlabel (y - titlebarShift + lblVshift) $ Color black $ Scale 0.1 0.1 $ Text name
  ]

  | otherwise
  = Blank
  where
    xlabel = x - 3.5 * (fromIntegral $ length name)

-- drawItem _ _ _ _ = Blank

onItem ::
  PanelContent
  -> (Float,Float)
  -> Maybe (Int,PanelItemType)
onItem (_, _, _, _, items) (x,y) = onItem' items (x,y)

onItem' ::
  [PanelItem]
  -> (Float,Float)
  -> Maybe (Int,PanelItemType)
onItem' [] _ = Nothing
onItem' ((itemId, _, itemType, x, y, w, h):is) p
  | pointInBox p (x+w/2,y-h/2-titlebarShift) (x-w/2,y+h/2-titlebarShift)
  = Just (itemId,itemType)

  | otherwise = onItem' is p

toggleItem ::
  [(Int,String)]
  -> (Int,PanelItemType)
  -> [(Int,String)]
toggleItem [] _ = []
toggleItem ((i,val):is) (t,ttype) | i == t    = (i, toggleVal ttype val):is
                                  | otherwise = (i,val):(toggleItem is (t,ttype))

toggleVal ::
  PanelItemType
  -> String
  -> String
toggleVal CheckButton "N" = "Y"
toggleVal CheckButton "Y" = "N"
toggleVal _ n             = n