content: {-# LANGUAGE
      DeriveDataTypeable #-}
  
  -- | Represents events in an IRC channel.
  -- These do not correspond precisely to messages of the IRC
  -- protocol.  They provide a somewhat higher-level view.
  
  module Data.IRC.Event
    ( -- * Events
      Nick   (..)
    , Event  (..)
    , EventAt(..)
  
      -- * Generic events
    , GenericEvent(..)
    , decompose
    ) where
  
  import qualified Data.Time as Time
  import qualified Data.Text as T
  
  import Data.Typeable ( Typeable )
  import Data.Data     ( Data, Constr, toConstr )
  
  -- | Event with timestamp.
  data EventAt
    = EventAt Time.UTCTime Event  -- ^ Event with timestamp.
    | NoParse T.Text              -- ^ Unparsable line.
    deriving (Show, Eq, Ord, Typeable)
    -- UTCTime lacks Data, so we can't derive it.
    -- We don't want to force that orphan instance on users.
  
  -- | IRC nicks.
  newtype Nick = Nick T.Text
    deriving (Show, Eq, Ord, Typeable, Data)
  
  -- | Events in an IRC channel.
  data Event
    = Join   Nick      T.Text  -- ^ User joined.
    | Part   Nick      T.Text  -- ^ User left the channel.
    | Quit   Nick      T.Text  -- ^ User quit the server.
    | ReNick Nick Nick         -- ^ User changed from one to another nick.
    | Talk   Nick      T.Text  -- ^ User spoke (@PRIVMSG@).
    | Notice Nick      T.Text  -- ^ User spoke (@NOTICE@).
    | Act    Nick      T.Text  -- ^ User acted (@CTCP ACTION@).
    | Kick   Nick Nick T.Text  -- ^ User was kicked by user.
    | Mode   Nick      T.Text  -- ^ User set mode on the channel.
    | Log              T.Text  -- ^ Logging started or stopped.
    | Topic            T.Text  -- ^ Topic listing or change.
    | Names            T.Text  -- ^ Users list.
    deriving (Show, Eq, Ord, Typeable, Data)
  
  -- | For working with @'Event'@s generically.
  --
  -- Indicates the \"subject\" of an event, if any, followed
  -- by other text.
  --
  -- The subject of a @'ReNick'@ event is the old nick.
  data GenericEvent
    = GenericEvent Constr (Maybe Nick) [T.Text]
    deriving (Show, Eq, Typeable)
  
  -- | Decompose an @'Event'@ into a @'GenericEvent'@.
  decompose :: Event -> GenericEvent
  decompose x = go x where
    c = GenericEvent $ toConstr x
  
    go (Join   n t) = c (Just n) [t]
    go (Part   n t) = c (Just n) [t]
    go (Quit   n t) = c (Just n) [t]
    go (Talk   n t) = c (Just n) [t]
    go (Notice n t) = c (Just n) [t]
    go (Act    n t) = c (Just n) [t]
    go (Mode   n t) = c (Just n) [t]
  
    go (Log   t) = c Nothing [t]
    go (Topic t) = c Nothing [t]
    go (Names t) = c Nothing [t]
  
    go (ReNick n (Nick t)) = c (Just n) [t]
    go (Kick a (Nick b) t) = c (Just a) [b,t]
  