{-# LANGUAGE OverloadedStrings, TypeFamilies, TupleSections, CPP #-}
-- | Events relating to mouse clicks and movement.
module Haste.Events.MouseEvents (
    MouseEvent (..), MouseData (..), MouseButton (..)
  ) where
import Haste.Events.Core
import Haste.Foreign
#if __GLASGOW_HASKELL__ < 710
import Control.Applicative
#endif

data MouseButton = MouseLeft | MouseMiddle | MouseRight
  deriving (Show, Eq, Enum)

instance FromAny MouseButton where
  fromAny = fmap toEnum . fromAny

-- | Event data for mouse events.
data MouseData = MouseData {
    -- | Mouse coordinates.
    mouseCoords      :: !(Int, Int),
    -- | Pressed mouse button, if any.
    mouseButton      :: !(Maybe MouseButton),
    -- | (x, y, z) mouse wheel delta. Always all zeroes except for 'Wheel'.
    mouseWheelDeltas :: !(Double, Double, Double)
  }

data MouseEvent
  = Click
  | DblClick
  | MouseDown
  | MouseUp
  | MouseMove
  | MouseOver
  | MouseOut
  | Wheel

instance Event MouseEvent where
  type EventData MouseEvent = MouseData
  eventName Click     = "click"
  eventName DblClick  = "dblclick"
  eventName MouseDown = "mousedown"
  eventName MouseUp   = "mouseup"
  eventName MouseMove = "mousemove"
  eventName MouseOver = "mouseover"
  eventName MouseOut  = "mouseout"
  eventName Wheel     = "wheel"
  eventData Wheel e =
    MouseData <$> jsGetMouseCoords e
              <*> pure Nothing
              <*> ((,,) <$> (get e "deltaX")
                        <*> (get e "deltaY")
                        <*> (get e "deltaZ"))

  eventData _ e =
    MouseData <$> jsGetMouseCoords e
              <*> get e "button"
              <*> pure (0,0,0)

jsGetMouseCoords :: JSAny -> IO (Int, Int)
jsGetMouseCoords = ffi "jsGetMouseCoords"