    --
    -- Copyright (c) 2012 Mark Dittmer - http://www.markdittmer.org
    -- Developed for a Google Summer of Code project - http://gsoc2012.markdittmer.org
    --
    {-# LANGUAGE CPP #-}

    module System.FSNotify.Types (
      act
      , ActionPredicate
      , Action
      , DebounceFn
      , WatchConfig(..)
      , WatchMode(..)
      , ThreadingMode(..)
      , Event(..)
      , EventIsDirectory(..)
      , EventCallback
      , EventChannel
      , EventAndActionChannel
      , IOEvent
      ) where

    import Control.Concurrent.Chan
    import Control.Exception.Safe
    import Data.IORef (IORef)
    import Data.Time.Clock (UTCTime)
    import Prelude hiding (FilePath)
    import System.FilePath

    data EventIsDirectory = IsFile | IsDirectory
      deriving (Int -> EventIsDirectory -> ShowS
    [EventIsDirectory] -> ShowS
    EventIsDirectory -> String
    (Int -> EventIsDirectory -> ShowS)
    -> (EventIsDirectory -> String)
    -> ([EventIsDirectory] -> ShowS)
    -> Show EventIsDirectory
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> EventIsDirectory -> ShowS
    showsPrec :: Int -> EventIsDirectory -> ShowS
    $cshow :: EventIsDirectory -> String
    show :: EventIsDirectory -> String
    $cshowList :: [EventIsDirectory] -> ShowS
    showList :: [EventIsDirectory] -> ShowS
    Show, EventIsDirectory -> EventIsDirectory -> Bool
    (EventIsDirectory -> EventIsDirectory -> Bool)
    -> (EventIsDirectory -> EventIsDirectory -> Bool)
    -> Eq EventIsDirectory
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: EventIsDirectory -> EventIsDirectory -> Bool
    == :: EventIsDirectory -> EventIsDirectory -> Bool
    $c/= :: EventIsDirectory -> EventIsDirectory -> Bool
    /= :: EventIsDirectory -> EventIsDirectory -> Bool
    Eq)

    -- | A file event reported by a file watcher. Each event contains the
    -- canonical path for the file and a timestamp guaranteed to be after the
    -- event occurred (timestamps represent current time when FSEvents receives
    -- it from the OS and/or platform-specific Haskell modules).
    data Event =
        Added { Event -> String
    eventPath :: FilePath, Event -> UTCTime
    eventTime :: UTCTime, Event -> EventIsDirectory
    eventIsDirectory :: EventIsDirectory }
      | Modified { eventPath :: FilePath, eventTime :: UTCTime, eventIsDirectory :: EventIsDirectory }
      | ModifiedAttributes { eventPath :: FilePath, eventTime :: UTCTime, eventIsDirectory :: EventIsDirectory }
      | Removed { eventPath :: FilePath, eventTime :: UTCTime, eventIsDirectory :: EventIsDirectory }
      -- | Note: Linux-only
      | WatchedDirectoryRemoved  { eventPath :: FilePath, eventTime :: UTCTime, eventIsDirectory :: EventIsDirectory }
      -- | Note: Linux-only
      | CloseWrite  { eventPath :: FilePath, eventTime :: UTCTime, eventIsDirectory :: EventIsDirectory }
      -- | Note: Linux-only
      | Unknown  { eventPath :: FilePath, eventTime :: UTCTime, eventIsDirectory :: EventIsDirectory, Event -> String
    eventString :: String }
      deriving (Event -> Event -> Bool
    (Event -> Event -> Bool) -> (Event -> Event -> Bool) -> Eq Event
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: Event -> Event -> Bool
    == :: Event -> Event -> Bool
    $c/= :: Event -> Event -> Bool
    /= :: Event -> Event -> Bool
    Eq, Int -> Event -> ShowS
    [Event] -> ShowS
    Event -> String
    (Int -> Event -> ShowS)
    -> (Event -> String) -> ([Event] -> ShowS) -> Show Event
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> Event -> ShowS
    showsPrec :: Int -> Event -> ShowS
    $cshow :: Event -> String
    show :: Event -> String
    $cshowList :: [Event] -> ShowS
    showList :: [Event] -> ShowS
    Show)

    type EventChannel = Chan Event

    type EventCallback = Event -> IO ()

    type EventAndActionChannel = Chan (Event, Action)

    -- | Method of watching for changes.
    data WatchMode =
      WatchModePoll {
        WatchMode -> Int
    watchModePollInterval :: Int
        -- ^ Polling interval in microseconds.
      }
      -- ^ Detect changes by polling the filesystem. Less efficient and may miss fast changes. Not recommended
      -- unless you're experiencing problems with 'WatchModeOS' (or 'WatchModeOS' is not supported on your platform).
    #ifdef HAVE_NATIVE_WATCHER
      | WatchModeOS
      -- ^ Use OS-specific mechanisms to be notified of changes (inotify on Linux, FSEvents on OSX, etc.).
      -- Not currently available on e.g. *BSD and Wasm/WASI.
    #endif

    data ThreadingMode =
      SingleThread
      -- ^ Use a single thread for the entire 'Manager'. Event handler callbacks will run sequentially.
      | ThreadPerWatch
      -- ^ Use a single thread for each watch (i.e. each call to 'watchDir', 'watchTree', etc.).
      -- Callbacks within a watch will run sequentially but callbacks from different watches may be interleaved.
      | ThreadPerEvent
      -- ^ Launch a separate thread for every event handler.

    -- | Watch configuration.
    data WatchConfig = WatchConfig
      { WatchConfig -> WatchMode
    confWatchMode :: WatchMode
        -- ^ Watch mode to use.
      , WatchConfig -> ThreadingMode
    confThreadingMode :: ThreadingMode
        -- ^ Threading mode to use.
      , WatchConfig -> SomeException -> IO ()
    confOnHandlerException :: SomeException -> IO ()
        -- ^ Called when a handler throws an exception.
      }

    type IOEvent = IORef Event

    -- | A predicate used to determine whether to act on an event.
    type ActionPredicate = Event -> Bool

    -- | An action to be performed in response to an event.
    type Action = Event -> IO ()

    -- | A general debouncing function.
    type DebounceFn = Action -> IO Action

    -- | Predicate to always act.
    act :: ActionPredicate
    act :: Event -> Bool
    act Event
    _ = Bool
    True