{-# LANGUAGE RankNTypes, FlexibleContexts, ConstraintKinds #-}

{-
  This module is part of Antisplice.
  Copyleft (c) 2014 Marvin Cohrs

  All wrongs reversed. Sharing is an act of love, not crime.
  Please share Antisplice with everyone you like.

  Antisplice is free software: you can redistribute it and/or modify
  it under the terms of the GNU Affero General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  Antisplice is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  GNU Affero General Public License for more details.

  You should have received a copy of the GNU Affero General Public License
  along with Antisplice. If not, see <http://www.gnu.org/licenses/>.
-}

-- | Provides setters for the various events
module Game.Antisplice.Events (
  OnEnter(..), OnFirstEnter(..), OnLook(..), OnAnnounce(..), OnSight(..), OnFirstSight(..), OnAcquire(..), OnFirstAcquire(..),
  OnInspection(..), OnFirstInspection(..), OnLookInto(..), OnRead(..), OnRoomEnter(..), OnRoomLeave(..), OnTakeDamage(..),
  OnDie(..), OnEat(..), OnDrink(..), OnUse(..)
  ) where

import Game.Antisplice.Monad
import Game.Antisplice.Rooms
import Game.Antisplice.Monad.Dungeon

roomOnFirstEnter :: MonadRoom m => Handler -> m ()
roomOnFirstEnter t = modifyRoomState $ \s -> s{roomTriggerOnFirstEnterOf=t}

roomOnEachEnter :: MonadRoom m => Handler -> m ()
roomOnEachEnter t = modifyRoomState $ \s -> s{roomTriggerOnEachEnterOf=t}

roomOnLook :: MonadRoom m => Handler -> m ()
roomOnLook t = modifyRoomState $ \s -> s{roomTriggerOnLookOf=t}

roomOnAnnounce :: MonadRoom m => Handler -> m ()
roomOnAnnounce t = modifyRoomState $ \s -> s{roomTriggerOnAnnounceOf=t}

objectOnFirstSight :: MonadObject m => Handler -> m ()
objectOnFirstSight t = modifyObjectState $ \s -> s{objectTriggerOnFirstSightOf=t}

objectOnEachSight :: MonadObject m => Handler -> m ()
objectOnEachSight t = modifyObjectState $ \s -> s{objectTriggerOnEachSightOf=t}

objectOnFirstAcquire :: MonadObject m => Handler -> m ()
objectOnFirstAcquire t = modifyObjectState $ \s -> s{objectTriggerOnFirstAcquireOf=t}

objectOnEachAcquire :: MonadObject m => Handler -> m ()
objectOnEachAcquire t = modifyObjectState $ \s -> s{objectTriggerOnEachAcquireOf=t}

objectOnFirstInspection :: MonadObject m => Handler -> m ()
objectOnFirstInspection t = modifyObjectState $ \s -> s{objectTriggerOnFirstInspectionOf=t}

objectOnEachInspection :: MonadObject m => Handler -> m ()
objectOnEachInspection t = modifyObjectState $ \s -> s{objectTriggerOnEachInspectionOf=t}

objectOnLookAt :: MonadObject m => Handler -> m ()
objectOnLookAt t = modifyObjectState $ \s -> s{objectTriggerOnLookAtOf=t}

objectOnLookInto :: MonadObject m => Handler -> m ()
objectOnLookInto t = modifyObjectState $ \s -> s{objectTriggerOnLookIntoOf=t}

objectOnRead :: MonadObject m => Handler -> m ()
objectOnRead t = modifyObjectState $ \s -> s{objectTriggerOnReadOf=t}

objectOnEnter :: MonadObject m => Handler -> m ()
objectOnEnter t = modifyObjectState $ \s -> s{objectTriggerOnEnterOf=t}

objectOnRoomEnter :: MonadObject m => Handler -> m ()
objectOnRoomEnter t = modifyObjectState $ \s -> s{objectTriggerOnRoomEnterOf=t}

objectOnRoomLeave :: MonadObject m => Handler -> m ()
objectOnRoomLeave t = modifyObjectState $ \s -> s{objectTriggerOnRoomLeaveOf=t}

objectOnAnnounce :: MonadObject m => Handler -> m ()
objectOnAnnounce t = modifyObjectState $ \s -> s{objectTriggerOnAnnounceOf=t}

objectOnDie :: MonadObject m => Handler -> m ()
objectOnDie t = modifyObjectState $ \s -> s{objectTriggerOnDieOf=t}

objectOnTakeDamage :: MonadObject m => Handler -> m ()
objectOnTakeDamage t = modifyObjectState $ \s -> s{objectTriggerOnTakeDamageOf=t}

objectOnDrink :: MonadObject m => Handler -> m ()
objectOnDrink t = modifyObjectState $ \s -> s{objectTriggerOnDrinkOf=t}

objectOnEat :: MonadObject m => Handler -> m ()
objectOnEat t = modifyObjectState $ \s -> s{objectTriggerOnEatOf=t}

objectOnUse :: MonadObject m => Handler -> m ()
objectOnUse t = modifyObjectState $ \s -> s{objectTriggerOnUseOf=t}

-- | Triggered when the user enters a room or object.
class OnEnter e where onEnter :: Handler -> e ()
instance Monad m => OnEnter (RoomT m) where onEnter = roomOnEachEnter
instance Monad m => OnEnter (ObjectT m) where onEnter = objectOnEnter

-- | Triggered when the user enters a room the first time.
class OnFirstEnter e where onFirstEnter :: Handler -> e ()
instance Monad m => OnFirstEnter (RoomT m) where onFirstEnter = roomOnFirstEnter

-- | Triggered when the user looks around or looks at a specific object.
class OnLook e where onLook :: Handler -> e ()
instance Monad m => OnLook (RoomT m) where onLook = roomOnLook
instance Monad m => OnLook (ObjectT m) where onLook = objectOnLookAt

-- | Triggered when the user looks into a specific object.
class OnLookInto e where onLookInto :: Handler -> e ()
instance Monad m => OnLookInto (ObjectT m) where onLookInto = objectOnLookInto

-- | Triggered when (a) the room is announced (e.g. when entered), (b) the user looks around in the room containing the object.
class OnAnnounce e where onAnnounce :: Handler -> e ()
instance Monad m => OnAnnounce (RoomT m) where onAnnounce = roomOnAnnounce
instance Monad m => OnAnnounce (ObjectT m) where onAnnounce = objectOnAnnounce

-- | Triggered when the user sees the object (e.g. he enters its room).
class OnSight e where onSight :: Handler -> e ()
instance Monad m => OnSight (ObjectT m) where onSight = objectOnEachSight

-- | Triggered when the user sees the object the first time.
class OnFirstSight e where onFirstSight :: Handler -> e ()
instance Monad m => OnFirstSight (ObjectT m) where onFirstSight = objectOnFirstSight

-- | Triggered when the user acquires the object.
class OnAcquire e where onAcquire :: Handler -> e ()
instance Monad m => OnAcquire (ObjectT m) where onAcquire = objectOnEachAcquire

-- | Triggered when the user acquires the object the first time.
class OnFirstAcquire e where onFirstAcquire :: Handler -> e ()
instance Monad m => OnFirstAcquire (ObjectT m) where onFirstAcquire = objectOnFirstAcquire

-- | Triggered when the user inspects the object (looks at/into it, listens to it, ...)
class OnInspection e where onInspection :: Handler -> e ()
instance Monad m => OnInspection (ObjectT m) where onInspection = objectOnEachInspection

-- | Triggered when the user inspects the object the first time.
class OnFirstInspection e where onFirstInspection :: Handler -> e ()
instance Monad m => OnFirstInspection (ObjectT m) where onFirstInspection = objectOnFirstInspection

-- | Triggered when the user reads the object.
class OnRead e where onRead :: Handler -> e ()
instance Monad m => OnRead (ObjectT m) where onRead = objectOnRead

-- | Triggered when the object (e.g. a mob with a route) enters the room of the user.
class OnRoomEnter e where onRoomEnter :: Handler -> e ()
instance Monad m => OnRoomEnter (ObjectT m) where onRoomEnter = objectOnRoomEnter

-- | Triggered when the object (e.g. a mob with a route) leaves the room of the user.
class OnRoomLeave e where onRoomLeave :: Handler -> e ()
instance Monad m => OnRoomLeave (ObjectT m) where onRoomLeave = objectOnRoomLeave

-- | Triggered when the object takes damage.
class OnTakeDamage e where onTakeDamage :: Handler -> e ()
instance Monad m => OnTakeDamage (ObjectT m) where onTakeDamage = objectOnTakeDamage

-- | Triggered when the object dies.
class OnDie e where onDie :: Handler -> e ()
instance Monad m => OnDie (ObjectT m) where onDie = objectOnDie

-- | Triggered when the object is drunk.
class OnDrink e where onDrink :: Handler -> e ()
instance Monad m => OnDrink (ObjectT m) where onDrink = objectOnDrink

-- | Triggered when the object is eaten
class OnEat e where onEat :: Handler -> e ()
instance Monad m => OnEat (ObjectT m) where onEat = objectOnEat

-- | Triggered when the object is used
class OnUse e where onUse :: Handler -> e ()
instance Monad m => OnUse (ObjectT m) where onUse = objectOnUse