-- |

module Hum.Utils where
import           Hum.Types
import           Hum.Rebuild
import           Brick.Types
import           Brick.Main
import           Brick.Widgets.List
import qualified Data.Vector                   as V
import qualified Data.Text                     as T
import           Network.MPD                    ( withMPD )
import qualified Network.MPD                   as MPD
import qualified Data.Map.Strict               as Map
import           Text.Printf                    ( printf )
import           Control.Lens
import qualified Data.Witherable.Class         as W

-- | A backwards function composition operator
infixl 8  ?
{-# INLINE (?) #-}
-- Make sure it has TWO args only on the left, so that it inlines
-- when applied to two functions, even if there is no final argument
(?)    :: (a -> b) -> (b -> c) -> a -> c
? :: (a -> b) -> (b -> c) -> a -> c
(?) a -> b
f b -> c
g = \a
x -> b -> c
g (a -> b
f a
x)

-- | Get comma seperated metedata from tag
meta :: Text -> MPD.Metadata -> MPD.Song -> Text
meta :: Text -> Metadata -> Song -> Text
meta Text
notFound Metadata
tag Song
song = Text -> ([Text] -> Text) -> Maybe [Text] -> Text
forall b a. b -> (a -> b) -> Maybe a -> b
maybe
  Text
notFound
  (Text -> [Text] -> Text
T.intercalate Text
",")
  (Value -> Text
forall a. ToString a => a -> Text
MPD.toText (Value -> Text) -> Maybe [Value] -> Maybe [Text]
forall (f :: * -> *) (g :: * -> *) a b.
(Functor f, Functor g) =>
(a -> b) -> f (g a) -> f (g b)
<<$>> Metadata -> Map Metadata [Value] -> Maybe [Value]
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Metadata
tag (Song -> Map Metadata [Value]
MPD.sgTags Song
song))

-- | like meta, but returns a Maybe for future use
mmeta :: MPD.Metadata -> MPD.Song -> Maybe Text
mmeta :: Metadata -> Song -> Maybe Text
mmeta Metadata
tag Song
song =
  Text -> [Text] -> Text
T.intercalate Text
"," ([Text] -> Text) -> Maybe [Text] -> Maybe Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Value -> Text
forall a. ToString a => a -> Text
MPD.toText (Value -> Text) -> Maybe [Value] -> Maybe [Text]
forall (f :: * -> *) (g :: * -> *) a b.
(Functor f, Functor g) =>
(a -> b) -> f (g a) -> f (g b)
<<$>> Metadata -> Map Metadata [Value] -> Maybe [Value]
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Metadata
tag (Song -> Map Metadata [Value]
MPD.sgTags Song
song))


secondsToTime :: Integer -> Text
secondsToTime :: Integer -> Text
secondsToTime Integer
sec =
  let (Integer
minutes, Integer
seconds) = Integer -> Integer -> (Integer, Integer)
forall a. Integral a => a -> a -> (a, a)
divMod Integer
sec Integer
60
  in  String -> Text
forall a. ToText a => a -> Text
toText (String -> Integer -> Integer -> String
forall r. PrintfType r => String -> r
printf String
"%d:%02d" Integer
minutes Integer
seconds :: String)

updateExtentMap :: EventM Name (Map Name (Maybe (Extent Name)))
updateExtentMap :: EventM Name (Map Name (Maybe (Extent Name)))
updateExtentMap = do
  Maybe (Extent Name)
queueE      <- Name -> EventM Name (Maybe (Extent Name))
forall n. Eq n => n -> EventM n (Maybe (Extent n))
lookupExtent Name
Queue
  Maybe (Extent Name)
nowPlayingE <- Name -> EventM Name (Maybe (Extent Name))
forall n. Eq n => n -> EventM n (Maybe (Extent n))
lookupExtent Name
NowPlaying
  Maybe (Extent Name)
libLeftE    <- Name -> EventM Name (Maybe (Extent Name))
forall n. Eq n => n -> EventM n (Maybe (Extent n))
lookupExtent Name
LibraryLeft
  Maybe (Extent Name)
libMidE     <- Name -> EventM Name (Maybe (Extent Name))
forall n. Eq n => n -> EventM n (Maybe (Extent n))
lookupExtent Name
LibraryMid
  Maybe (Extent Name)
libRightE   <- Name -> EventM Name (Maybe (Extent Name))
forall n. Eq n => n -> EventM n (Maybe (Extent n))
lookupExtent Name
LibraryRight
  Maybe (Extent Name)
playLeftE   <- Name -> EventM Name (Maybe (Extent Name))
forall n. Eq n => n -> EventM n (Maybe (Extent n))
lookupExtent Name
PlaylistLeft
  Maybe (Extent Name)
playRightE  <- Name -> EventM Name (Maybe (Extent Name))
forall n. Eq n => n -> EventM n (Maybe (Extent n))
lookupExtent Name
PlaylistRight
  let extentMap :: Map Name (Maybe (Extent Name))
extentMap = [(Name, Maybe (Extent Name))] -> Map Name (Maybe (Extent Name))
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList
        [ (Name
Queue        , Maybe (Extent Name)
queueE)
        , (Name
NowPlaying   , Maybe (Extent Name)
nowPlayingE)
        , (Name
LibraryLeft  , Maybe (Extent Name)
libLeftE)
        , (Name
LibraryMid   , Maybe (Extent Name)
libMidE)
        , (Name
LibraryRight , Maybe (Extent Name)
libRightE)
        , (Name
PlaylistLeft , Maybe (Extent Name)
playLeftE)
        , (Name
PlaylistRight, Maybe (Extent Name)
playRightE)
        ]
  Map Name (Maybe (Extent Name))
-> EventM Name (Map Name (Maybe (Extent Name)))
forall (f :: * -> *) a. Applicative f => a -> f a
pure Map Name (Maybe (Extent Name))
extentMap

deleteHighlightedfromQ :: MPD.MonadMPD m => SongList -> m ()
deleteHighlightedfromQ :: SongList -> m ()
deleteHighlightedfromQ SongList
ls =
  let (SongList
hls :: SongList) = ((Song, Bool) -> Bool) -> SongList -> SongList
forall (f :: * -> *) a. Filterable f => (a -> Bool) -> f a -> f a
W.filter (Song, Bool) -> Bool
forall a b. (a, b) -> b
snd SongList
ls
  in  SongList -> ((Song, Bool) -> m ()) -> m ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ SongList
hls (\(Song, Bool)
s -> Maybe Id -> (Id -> m ()) -> m ()
forall (f :: * -> *) a.
Applicative f =>
Maybe a -> (a -> f ()) -> f ()
whenJust (Song -> Maybe Id
MPD.sgId (Song -> Maybe Id)
-> ((Song, Bool) -> Song) -> (Song, Bool) -> Maybe Id
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Song, Bool) -> Song
forall a b. (a, b) -> a
fst ((Song, Bool) -> Maybe Id) -> (Song, Bool) -> Maybe Id
forall a b. (a -> b) -> a -> b
$ (Song, Bool)
s) Id -> m ()
forall (m :: * -> *). MonadMPD m => Id -> m ()
MPD.deleteId)
        m () -> m () -> m ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Maybe Id -> (Id -> m ()) -> m ()
forall (f :: * -> *) a.
Applicative f =>
Maybe a -> (a -> f ()) -> f ()
whenJust
             ((Song -> Maybe Id
MPD.sgId (Song -> Maybe Id)
-> ((Int, (Song, Bool)) -> Song) -> (Int, (Song, Bool)) -> Maybe Id
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Song, Bool) -> Song
forall a b. (a, b) -> a
fst ((Song, Bool) -> Song)
-> ((Int, (Song, Bool)) -> (Song, Bool))
-> (Int, (Song, Bool))
-> Song
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Int, (Song, Bool)) -> (Song, Bool)
forall a b. (a, b) -> b
snd) ((Int, (Song, Bool)) -> Maybe Id)
-> Maybe (Int, (Song, Bool)) -> Maybe Id
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< SongList -> Maybe (Int, (Song, Bool))
forall (t :: * -> *) n e.
(Splittable t, Foldable t) =>
GenericList n t e -> Maybe (Int, e)
listSelectedElement SongList
ls)
             Id -> m ()
forall (m :: * -> *). MonadMPD m => Id -> m ()
MPD.deleteId

deleteAll :: MPD.MonadMPD m => SongList -> m ()
deleteAll :: SongList -> m ()
deleteAll SongList
ls = SongList -> ((Song, Bool) -> m ()) -> m ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ SongList
ls (\(Song, Bool)
s -> Maybe Id -> (Id -> m ()) -> m ()
forall (f :: * -> *) a.
Applicative f =>
Maybe a -> (a -> f ()) -> f ()
whenJust (Song -> Maybe Id
MPD.sgId (Song -> Maybe Id)
-> ((Song, Bool) -> Song) -> (Song, Bool) -> Maybe Id
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Song, Bool) -> Song
forall a b. (a, b) -> a
fst ((Song, Bool) -> Maybe Id) -> (Song, Bool) -> Maybe Id
forall a b. (a -> b) -> a -> b
$ (Song, Bool)
s) Id -> m ()
forall (m :: * -> *). MonadMPD m => Id -> m ()
MPD.deleteId)

pasteSongstoQ :: MPD.MonadMPD m => SongList -> SongList -> m ()
pasteSongstoQ :: SongList -> SongList -> m ()
pasteSongstoQ SongList
clip SongList
ls =
  let pos :: Maybe Int
pos         = SongList -> Maybe Int
forall n (t :: * -> *) e. GenericList n t e -> Maybe Int
listSelected SongList
ls
      indexedClip :: Vector (Int, Path)
indexedClip = Vector Path -> Vector (Int, Path)
forall a. Vector a -> Vector (Int, a)
V.indexed (Vector Path -> Vector (Int, Path))
-> Vector Path -> Vector (Int, Path)
forall a b. (a -> b) -> a -> b
$ Song -> Path
MPD.sgFilePath (Song -> Path) -> ((Song, Bool) -> Song) -> (Song, Bool) -> Path
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Song, Bool) -> Song
forall a b. (a, b) -> a
fst ((Song, Bool) -> Path) -> Vector (Song, Bool) -> Vector Path
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> SongList -> Vector (Song, Bool)
forall n (t :: * -> *) e. GenericList n t e -> t e
listElements SongList
clip
  in  Vector (Int, Path) -> ((Int, Path) -> m Id) -> m ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ Vector (Int, Path)
indexedClip (\(Int
n, Path
song) -> Path -> Maybe Int -> m Id
forall (m :: * -> *). MonadMPD m => Path -> Maybe Int -> m Id
MPD.addId Path
song (Maybe Int -> m Id) -> Maybe Int -> m Id
forall a b. (a -> b) -> a -> b
$ (Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1)) (Int -> Int) -> Maybe Int -> Maybe Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe Int
pos)

getHighlighted
  :: (Eq e, W.Filterable t, Foldable t, Splittable t)
  => GenericList n t (e, Highlight)
  -> GenericList n t (e, Highlight)
getHighlighted :: GenericList n t (e, Bool) -> GenericList n t (e, Bool)
getHighlighted GenericList n t (e, Bool)
ls = GenericList n t (e, Bool)
hls where
  hls :: GenericList n t (e, Bool)
hls = ((e, Bool) -> Bool)
-> GenericList n t (e, Bool) -> GenericList n t (e, Bool)
forall (f :: * -> *) a. Filterable f => (a -> Bool) -> f a -> f a
W.filter
    (\(e
el, Bool
hl) -> Bool
hl Bool -> Bool -> Bool
|| (e, Bool) -> Maybe (e, Bool)
forall a. a -> Maybe a
Just (e
el, Bool
hl) Maybe (e, Bool) -> Maybe (e, Bool) -> Bool
forall a. Eq a => a -> a -> Bool
== ((Int, (e, Bool)) -> (e, Bool)
forall a b. (a, b) -> b
snd ((Int, (e, Bool)) -> (e, Bool))
-> Maybe (Int, (e, Bool)) -> Maybe (e, Bool)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> GenericList n t (e, Bool) -> Maybe (Int, (e, Bool))
forall (t :: * -> *) n e.
(Splittable t, Foldable t) =>
GenericList n t e -> Maybe (Int, e)
listSelectedElement GenericList n t (e, Bool)
ls))
    GenericList n t (e, Bool)
ls

listPaste
  :: (Splittable t, Semigroup (t e))
  => GenericList n t e
  -> GenericList n t e
  -> GenericList n t e
listPaste :: GenericList n t e -> GenericList n t e -> GenericList n t e
listPaste GenericList n t e
paste GenericList n t e
ls =
  let es :: t e
es         = GenericList n t e -> t e
forall n (t :: * -> *) e. GenericList n t e -> t e
listElements GenericList n t e
ls
      pos :: Int
pos        = Int -> Maybe Int -> Int
forall a. a -> Maybe a -> a
fromMaybe Int
0 (GenericList n t e -> Maybe Int
forall n (t :: * -> *) e. GenericList n t e -> Maybe Int
listSelected GenericList n t e
ls)
      (t e
es1, t e
es2) = Int -> t e -> (t e, t e)
forall (t :: * -> *) a. Splittable t => Int -> t a -> (t a, t a)
Brick.Widgets.List.splitAt (Int
pos Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1) t e
es
  in  GenericList n t e
ls { listElements :: t e
listElements = t e
es1 t e -> t e -> t e
forall a. Semigroup a => a -> a -> a
<> GenericList n t e -> t e
forall n (t :: * -> *) e. GenericList n t e -> t e
listElements GenericList n t e
paste t e -> t e -> t e
forall a. Semigroup a => a -> a -> a
<> t e
es2 }

deleteHighlighted ::  HState
    -> Lens' HState SongList
    -> HState
deleteHighlighted :: HState -> Lens' HState SongList -> HState
deleteHighlighted HState
st Lens' HState SongList
lns = HState
st HState -> (HState -> HState) -> HState
forall a b. a -> (a -> b) -> b
& (Clipboard -> Identity Clipboard) -> HState -> Identity HState
Lens' HState Clipboard
clipboardL ((Clipboard -> Identity Clipboard) -> HState -> Identity HState)
-> ((SongList -> Identity SongList)
    -> Clipboard -> Identity Clipboard)
-> (SongList -> Identity SongList)
-> HState
-> Identity HState
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (SongList -> Identity SongList) -> Clipboard -> Identity Clipboard
Lens' Clipboard SongList
clSongsL ((SongList -> Identity SongList) -> HState -> Identity HState)
-> SongList -> HState -> HState
forall s t a b. ASetter s t a b -> b -> s -> t
.~ (HState
st HState -> Getting SongList HState SongList -> SongList
forall s a. s -> Getting a s a -> a
^. Getting SongList HState SongList
Lens' HState SongList
lns SongList -> (SongList -> SongList) -> SongList
forall a b. a -> (a -> b) -> b
& SongList -> SongList
forall (t :: * -> *) n e.
Traversable t =>
GenericList n t (e, Bool) -> GenericList n t (e, Bool)
listHighlight (SongList -> SongList)
-> (SongList -> SongList) -> SongList -> SongList
forall a b c. (a -> b) -> (b -> c) -> a -> c
? ((Song, Bool) -> Bool) -> SongList -> SongList
forall (f :: * -> *) a. Filterable f => (a -> Bool) -> f a -> f a
W.filter (Song, Bool) -> Bool
forall a b. (a, b) -> b
snd (SongList -> SongList)
-> (SongList -> SongList) -> SongList -> SongList
forall a b c. (a -> b) -> (b -> c) -> a -> c
? SongList -> SongList
forall (t :: * -> *) n e.
Traversable t =>
GenericList n t (e, Bool) -> GenericList n t (e, Bool)
listUnhighlightAll)
                              HState -> (HState -> HState) -> HState
forall a b. a -> (a -> b) -> b
& (SongList -> Identity SongList) -> HState -> Identity HState
Lens' HState SongList
lns ((SongList -> Identity SongList) -> HState -> Identity HState)
-> (SongList -> SongList) -> HState -> HState
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ SongList -> SongList
forall (t :: * -> *) n e.
Traversable t =>
GenericList n t (e, Bool) -> GenericList n t (e, Bool)
listHighlight (SongList -> SongList)
-> (SongList -> SongList) -> SongList -> SongList
forall a b c. (a -> b) -> (b -> c) -> a -> c
? ((Song, Bool) -> Bool) -> SongList -> SongList
forall (f :: * -> *) a. Filterable f => (a -> Bool) -> f a -> f a
W.filter (Bool -> Bool
not (Bool -> Bool) -> ((Song, Bool) -> Bool) -> (Song, Bool) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Song, Bool) -> Bool
forall a b. (a, b) -> b
snd)

-- | toggle selected items highlight status
listToggleHighlight :: Traversable t => GenericList n t (e,Highlight) -> GenericList n t (e,Highlight)
listToggleHighlight :: GenericList n t (e, Bool) -> GenericList n t (e, Bool)
listToggleHighlight = ((e, Bool) -> (e, Bool))
-> GenericList n t (e, Bool) -> GenericList n t (e, Bool)
forall (t :: * -> *) e n.
Traversable t =>
(e -> e) -> GenericList n t e -> GenericList n t e
listModify ((Bool -> Bool) -> (e, Bool) -> (e, Bool)
forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second Bool -> Bool
not)


-- | Highlight selcted item status
listHighlight :: Traversable t => GenericList n t (e,Highlight) -> GenericList n t (e,Highlight)
listHighlight :: GenericList n t (e, Bool) -> GenericList n t (e, Bool)
listHighlight = ((e, Bool) -> (e, Bool))
-> GenericList n t (e, Bool) -> GenericList n t (e, Bool)
forall (t :: * -> *) e n.
Traversable t =>
(e -> e) -> GenericList n t e -> GenericList n t e
listModify ((Bool -> Bool) -> (e, Bool) -> (e, Bool)
forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second (Bool -> Bool -> Bool
forall a b. a -> b -> a
const Bool
True))

listUnhighlightAll :: Traversable t => GenericList n t (e,Highlight) -> GenericList n t (e,Highlight)
listUnhighlightAll :: GenericList n t (e, Bool) -> GenericList n t (e, Bool)
listUnhighlightAll = ((e, Bool) -> (e, Bool))
-> GenericList n t (e, Bool) -> GenericList n t (e, Bool)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Bool -> Bool) -> (e, Bool) -> (e, Bool)
forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second ((Bool -> Bool) -> (e, Bool) -> (e, Bool))
-> (Bool -> Bool) -> (e, Bool) -> (e, Bool)
forall a b. (a -> b) -> a -> b
$ Bool -> Bool -> Bool
forall a b. a -> b -> a
const Bool
False)

saveListToPl :: MPD.MonadMPD m => SongList -> Text -> m ()
saveListToPl :: SongList -> Text -> m ()
saveListToPl SongList
ls Text
name =
  let songpaths :: Vector Path
songpaths = Song -> Path
MPD.sgFilePath (Song -> Path) -> ((Song, Bool) -> Song) -> (Song, Bool) -> Path
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Song, Bool) -> Song
forall a b. (a, b) -> a
fst ((Song, Bool) -> Path) -> Vector (Song, Bool) -> Vector Path
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> SongList -> Vector (Song, Bool)
forall n (t :: * -> *) e. GenericList n t e -> t e
listElements SongList
ls
      name' :: PlaylistName
name'     = String -> PlaylistName
forall a. IsString a => String -> a
fromString (String -> PlaylistName)
-> (Text -> String) -> Text -> PlaylistName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
T.unpack (Text -> PlaylistName) -> Text -> PlaylistName
forall a b. (a -> b) -> a -> b
$ Text
name
  in  Vector Path -> (Path -> m ()) -> m ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ Vector Path
songpaths (PlaylistName -> Path -> m ()
forall (m :: * -> *). MonadMPD m => PlaylistName -> Path -> m ()
MPD.playlistAdd PlaylistName
name')

overwriteListToPl :: MPD.MonadMPD m => SongList -> Text -> m ()
overwriteListToPl :: SongList -> Text -> m ()
overwriteListToPl SongList
ls Text
name =
  let songpaths :: Vector Path
songpaths = Song -> Path
MPD.sgFilePath (Song -> Path) -> ((Song, Bool) -> Song) -> (Song, Bool) -> Path
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Song, Bool) -> Song
forall a b. (a, b) -> a
fst ((Song, Bool) -> Path) -> Vector (Song, Bool) -> Vector Path
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> SongList -> Vector (Song, Bool)
forall n (t :: * -> *) e. GenericList n t e -> t e
listElements SongList
ls
      name' :: PlaylistName
name'     = String -> PlaylistName
forall a. IsString a => String -> a
fromString (String -> PlaylistName)
-> (Text -> String) -> Text -> PlaylistName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
T.unpack (Text -> PlaylistName) -> Text -> PlaylistName
forall a b. (a -> b) -> a -> b
$ Text
name
  in PlaylistName -> m ()
forall (m :: * -> *). MonadMPD m => PlaylistName -> m ()
MPD.playlistClear PlaylistName
name' m () -> m () -> m ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>>
     Vector Path -> (Path -> m ()) -> m ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ Vector Path
songpaths (PlaylistName -> Path -> m ()
forall (m :: * -> *). MonadMPD m => PlaylistName -> Path -> m ()
MPD.playlistAdd PlaylistName
name')

saveEditedPl :: HState -> EventM n HState
saveEditedPl :: HState -> EventM n HState
saveEditedPl HState
st = do
  let plSongs :: SongList
plSongs = HState
st HState -> Getting SongList HState SongList -> SongList
forall s a. s -> Getting a s a -> a
^. (PlaylistsState -> Const SongList PlaylistsState)
-> HState -> Const SongList HState
Lens' HState PlaylistsState
playlistsL ((PlaylistsState -> Const SongList PlaylistsState)
 -> HState -> Const SongList HState)
-> ((SongList -> Const SongList SongList)
    -> PlaylistsState -> Const SongList PlaylistsState)
-> Getting SongList HState SongList
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (SongList -> Const SongList SongList)
-> PlaylistsState -> Const SongList PlaylistsState
Lens' PlaylistsState SongList
plSongsL
  let plName :: Text
plName = HState
st HState
-> Getting (List Name PlaylistName) HState (List Name PlaylistName)
-> List Name PlaylistName
forall s a. s -> Getting a s a -> a
^. (PlaylistsState -> Const (List Name PlaylistName) PlaylistsState)
-> HState -> Const (List Name PlaylistName) HState
Lens' HState PlaylistsState
playlistsL ((PlaylistsState -> Const (List Name PlaylistName) PlaylistsState)
 -> HState -> Const (List Name PlaylistName) HState)
-> ((List Name PlaylistName
     -> Const (List Name PlaylistName) (List Name PlaylistName))
    -> PlaylistsState -> Const (List Name PlaylistName) PlaylistsState)
-> Getting (List Name PlaylistName) HState (List Name PlaylistName)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (List Name PlaylistName
 -> Const (List Name PlaylistName) (List Name PlaylistName))
-> PlaylistsState -> Const (List Name PlaylistName) PlaylistsState
Lens' PlaylistsState (List Name PlaylistName)
plListL List Name PlaylistName -> (List Name PlaylistName -> Text) -> Text
forall a b. a -> (a -> b) -> b
& List Name PlaylistName -> Maybe (Int, PlaylistName)
forall (t :: * -> *) n e.
(Splittable t, Foldable t) =>
GenericList n t e -> Maybe (Int, e)
listSelectedElement (List Name PlaylistName -> Maybe (Int, PlaylistName))
-> (Maybe (Int, PlaylistName) -> PlaylistName)
-> List Name PlaylistName
-> PlaylistName
forall a b c. (a -> b) -> (b -> c) -> a -> c
? PlaylistName
-> ((Int, PlaylistName) -> PlaylistName)
-> Maybe (Int, PlaylistName)
-> PlaylistName
forall b a. b -> (a -> b) -> Maybe a -> b
maybe PlaylistName
"unnamed" (Int, PlaylistName) -> PlaylistName
forall a b. (a, b) -> b
snd (List Name PlaylistName -> PlaylistName)
-> (PlaylistName -> Text) -> List Name PlaylistName -> Text
forall a b c. (a -> b) -> (b -> c) -> a -> c
? PlaylistName -> Text
forall a. ToString a => a -> Text
MPD.toText
  Response ()
_ <- IO (Response ()) -> EventM n (Response ())
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Response ()) -> EventM n (Response ()))
-> (MPD () -> IO (Response ())) -> MPD () -> EventM n (Response ())
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MPD () -> IO (Response ())
forall a. MPD a -> IO (Response a)
withMPD (MPD () -> EventM n (Response ()))
-> MPD () -> EventM n (Response ())
forall a b. (a -> b) -> a -> b
$ SongList -> Text -> MPD ()
forall (m :: * -> *). MonadMPD m => SongList -> Text -> m ()
overwriteListToPl SongList
plSongs Text
plName
  HState -> EventM n HState
forall (f :: * -> *) a. Applicative f => a -> f a
pure HState
st

deleteSelectedPl :: HState -> EventM n HState
deleteSelectedPl :: HState -> EventM n HState
deleteSelectedPl HState
st = do
  let plName :: Maybe PlaylistName
plName = HState
st HState
-> Getting (List Name PlaylistName) HState (List Name PlaylistName)
-> List Name PlaylistName
forall s a. s -> Getting a s a -> a
^. (PlaylistsState -> Const (List Name PlaylistName) PlaylistsState)
-> HState -> Const (List Name PlaylistName) HState
Lens' HState PlaylistsState
playlistsL ((PlaylistsState -> Const (List Name PlaylistName) PlaylistsState)
 -> HState -> Const (List Name PlaylistName) HState)
-> ((List Name PlaylistName
     -> Const (List Name PlaylistName) (List Name PlaylistName))
    -> PlaylistsState -> Const (List Name PlaylistName) PlaylistsState)
-> Getting (List Name PlaylistName) HState (List Name PlaylistName)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (List Name PlaylistName
 -> Const (List Name PlaylistName) (List Name PlaylistName))
-> PlaylistsState -> Const (List Name PlaylistName) PlaylistsState
Lens' PlaylistsState (List Name PlaylistName)
plListL List Name PlaylistName
-> (List Name PlaylistName -> Maybe (Int, PlaylistName))
-> Maybe (Int, PlaylistName)
forall a b. a -> (a -> b) -> b
& List Name PlaylistName -> Maybe (Int, PlaylistName)
forall (t :: * -> *) n e.
(Splittable t, Foldable t) =>
GenericList n t e -> Maybe (Int, e)
listSelectedElement Maybe (Int, PlaylistName)
-> ((Int, PlaylistName) -> PlaylistName) -> Maybe PlaylistName
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> (Int, PlaylistName) -> PlaylistName
forall a b. (a, b) -> b
snd
  Response (Maybe ())
_ <- IO (Response (Maybe ())) -> EventM n (Response (Maybe ()))
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Response (Maybe ())) -> EventM n (Response (Maybe ())))
-> (MPD (Maybe ()) -> IO (Response (Maybe ())))
-> MPD (Maybe ())
-> EventM n (Response (Maybe ()))
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MPD (Maybe ()) -> IO (Response (Maybe ()))
forall a. MPD a -> IO (Response a)
withMPD (MPD (Maybe ()) -> EventM n (Response (Maybe ())))
-> MPD (Maybe ()) -> EventM n (Response (Maybe ()))
forall a b. (a -> b) -> a -> b
$ (PlaylistName -> MPD ()) -> Maybe PlaylistName -> MPD (Maybe ())
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse PlaylistName -> MPD ()
forall (m :: * -> *). MonadMPD m => PlaylistName -> m ()
MPD.rm Maybe PlaylistName
plName
  HState -> EventM n HState
forall (m :: * -> *). MonadIO m => HState -> m HState
rebuildPl HState
st

duplicatePlaylist :: MPD.PlaylistName -> HState -> EventM n HState
duplicatePlaylist :: PlaylistName -> HState -> EventM n HState
duplicatePlaylist PlaylistName
pl HState
st = do
  Vector Song
songs <- [Song] -> Vector Song
forall a. [a] -> Vector a
V.fromList ([Song] -> Vector Song)
-> (Either MPDError [Song] -> [Song])
-> Either MPDError [Song]
-> Vector Song
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Song] -> Either MPDError [Song] -> [Song]
forall b a. b -> Either a b -> b
fromRight [] (Either MPDError [Song] -> Vector Song)
-> EventM n (Either MPDError [Song]) -> EventM n (Vector Song)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (IO (Either MPDError [Song]) -> EventM n (Either MPDError [Song])
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Either MPDError [Song]) -> EventM n (Either MPDError [Song]))
-> (MPD [Song] -> IO (Either MPDError [Song]))
-> MPD [Song]
-> EventM n (Either MPDError [Song])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MPD [Song] -> IO (Either MPDError [Song])
forall a. MPD a -> IO (Response a)
withMPD (MPD [Song] -> EventM n (Either MPDError [Song]))
-> MPD [Song] -> EventM n (Either MPDError [Song])
forall a b. (a -> b) -> a -> b
$ PlaylistName -> MPD [Song]
forall (m :: * -> *). MonadMPD m => PlaylistName -> m [Song]
MPD.listPlaylistInfo PlaylistName
pl)
  [Text]
plNames <- (PlaylistName -> Text
forall a. ToString a => a -> Text
MPD.toText (PlaylistName -> Text) -> [PlaylistName] -> [Text]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>) ([PlaylistName] -> [Text])
-> (Either MPDError [PlaylistName] -> [PlaylistName])
-> Either MPDError [PlaylistName]
-> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [PlaylistName] -> Either MPDError [PlaylistName] -> [PlaylistName]
forall b a. b -> Either a b -> b
fromRight [] (Either MPDError [PlaylistName] -> [Text])
-> EventM n (Either MPDError [PlaylistName]) -> EventM n [Text]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (IO (Either MPDError [PlaylistName])
-> EventM n (Either MPDError [PlaylistName])
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Either MPDError [PlaylistName])
 -> EventM n (Either MPDError [PlaylistName]))
-> (MPD [PlaylistName] -> IO (Either MPDError [PlaylistName]))
-> MPD [PlaylistName]
-> EventM n (Either MPDError [PlaylistName])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MPD [PlaylistName] -> IO (Either MPDError [PlaylistName])
forall a. MPD a -> IO (Response a)
withMPD (MPD [PlaylistName] -> EventM n (Either MPDError [PlaylistName]))
-> MPD [PlaylistName] -> EventM n (Either MPDError [PlaylistName])
forall a b. (a -> b) -> a -> b
$ MPD [PlaylistName]
forall (m :: * -> *). MonadMPD m => m [PlaylistName]
MPD.listPlaylists)
  let newPlName :: Maybe Text
newPlName = (NonEmpty Text -> Text) -> [Text] -> Maybe Text
forall a b. (NonEmpty a -> b) -> [a] -> Maybe b
viaNonEmpty NonEmpty Text -> Text
forall (f :: * -> *) a. IsNonEmpty f a a "head" => f a -> a
head ([Text] -> Maybe Text) -> [Text] -> Maybe Text
forall a b. (a -> b) -> a -> b
$ (Text -> Bool) -> [Text] -> [Text]
forall a. (a -> Bool) -> [a] -> [a]
filter (Text -> [Text] -> Bool
forall (f :: * -> *) a.
(Foldable f, DisallowElem f, Eq a) =>
a -> f a -> Bool
`notElem` [Text]
plNames) ((Int -> Text) -> [Int] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map ((\Text
tx Int
num -> Text
tx Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"-copy" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Int -> Text
forall b a. (Show a, IsString b) => a -> b
show Int
num) (PlaylistName -> Text
forall a. ToString a => a -> Text
MPD.toText PlaylistName
pl)) [Int
1::Int ..])
  (String -> EventM n HState) -> Maybe String -> EventM n ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
(a -> f b) -> t a -> f ()
traverse_ (\String
pln -> String -> Vector Song -> HState -> EventM n HState
forall n. String -> Vector Song -> HState -> EventM n HState
songBulkAddtoPl String
pln Vector Song
songs HState
st) (Text -> String
T.unpack (Text -> String) -> Maybe Text -> Maybe String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe Text
newPlName)
  HState -> EventM n HState
forall (m :: * -> *). MonadIO m => HState -> m HState
rebuildPl HState
st

pastePlaylist :: HState -> EventM n HState
pastePlaylist :: HState -> EventM n HState
pastePlaylist HState
st = do
  let plName :: PlaylistName
plName = PlaylistName -> Maybe PlaylistName -> PlaylistName
forall a. a -> Maybe a -> a
fromMaybe PlaylistName
"<error>" (HState
st HState
-> Getting (Maybe PlaylistName) HState (Maybe PlaylistName)
-> Maybe PlaylistName
forall s a. s -> Getting a s a -> a
^. (Clipboard -> Const (Maybe PlaylistName) Clipboard)
-> HState -> Const (Maybe PlaylistName) HState
Lens' HState Clipboard
clipboardL ((Clipboard -> Const (Maybe PlaylistName) Clipboard)
 -> HState -> Const (Maybe PlaylistName) HState)
-> ((Maybe PlaylistName
     -> Const (Maybe PlaylistName) (Maybe PlaylistName))
    -> Clipboard -> Const (Maybe PlaylistName) Clipboard)
-> Getting (Maybe PlaylistName) HState (Maybe PlaylistName)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Maybe PlaylistName
 -> Const (Maybe PlaylistName) (Maybe PlaylistName))
-> Clipboard -> Const (Maybe PlaylistName) Clipboard
Lens' Clipboard (Maybe PlaylistName)
clPlNameL)
  PlaylistName -> HState -> EventM n HState
forall n. PlaylistName -> HState -> EventM n HState
duplicatePlaylist PlaylistName
plName HState
st

songBulkAddtoQ :: Bool -> V.Vector MPD.Song -> HState -> EventM n HState
songBulkAddtoQ :: Bool -> Vector Song -> HState -> EventM n HState
songBulkAddtoQ Bool
play Vector Song
songs HState
s = do
  let songPaths :: Vector Path
songPaths = Song -> Path
MPD.sgFilePath (Song -> Path) -> Vector Song -> Vector Path
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Vector Song
songs
  (Path -> EventM n (Response ())) -> Vector Path -> EventM n ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
(a -> f b) -> t a -> f ()
traverse_
    (\Path
sel -> IO (Response ()) -> EventM n (Response ())
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO
      (MPD () -> IO (Response ())
forall a. MPD a -> IO (Response a)
withMPD (MPD () -> IO (Response ())) -> MPD () -> IO (Response ())
forall a b. (a -> b) -> a -> b
$ Path -> Maybe Int -> MPD Id
forall (m :: * -> *). MonadMPD m => Path -> Maybe Int -> m Id
MPD.addId Path
sel Maybe Int
forall a. Maybe a
Nothing MPD Id -> (Id -> MPD ()) -> MPD ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= if Bool
play
        then Id -> MPD ()
forall (m :: * -> *). MonadMPD m => Id -> m ()
MPD.playId
        else MPD () -> Id -> MPD ()
forall a b. a -> b -> a
const MPD ()
forall (f :: * -> *). Applicative f => f ()
pass
      )
    )
    (Int -> Vector Path -> Vector Path
forall a. Int -> Vector a -> Vector a
V.take Int
1 Vector Path
songPaths)
  (Path -> EventM n (Response Id)) -> Vector Path -> EventM n ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
(a -> f b) -> t a -> f ()
traverse_ (\Path
sel -> IO (Response Id) -> EventM n (Response Id)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (MPD Id -> IO (Response Id)
forall a. MPD a -> IO (Response a)
withMPD (MPD Id -> IO (Response Id)) -> MPD Id -> IO (Response Id)
forall a b. (a -> b) -> a -> b
$ Path -> Maybe Int -> MPD Id
forall (m :: * -> *). MonadMPD m => Path -> Maybe Int -> m Id
MPD.addId Path
sel Maybe Int
forall a. Maybe a
Nothing))
            (Int -> Vector Path -> Vector Path
forall a. Int -> Vector a -> Vector a
V.drop Int
1 Vector Path
songPaths)
  Response (Maybe Song)
song <- IO (Response (Maybe Song)) -> EventM n (Response (Maybe Song))
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (MPD (Maybe Song) -> IO (Response (Maybe Song))
forall a. MPD a -> IO (Response a)
withMPD MPD (Maybe Song)
forall (m :: * -> *). MonadMPD m => m (Maybe Song)
MPD.currentSong)
  HState -> EventM n HState
forall (f :: * -> *) a. Applicative f => a -> f a
pure HState
s { currentSong :: Maybe Song
currentSong = Maybe Song -> Response (Maybe Song) -> Maybe Song
forall b a. b -> Either a b -> b
fromRight Maybe Song
forall a. Maybe a
Nothing Response (Maybe Song)
song, queue :: SongList
queue = HState -> SongList
queue HState
s }

songBulkAddtoPl :: String -> V.Vector MPD.Song -> HState -> EventM n HState
songBulkAddtoPl :: String -> Vector Song -> HState -> EventM n HState
songBulkAddtoPl String
pl Vector Song
songs HState
s = do
  let songPaths :: Vector Path
songPaths = Song -> Path
MPD.sgFilePath (Song -> Path) -> Vector Song -> Vector Path
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Vector Song
songs
  (Path -> EventM n (Response ())) -> Vector Path -> EventM n ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
(a -> f b) -> t a -> f ()
traverse_
    (\Path
sel -> IO (Response ()) -> EventM n (Response ())
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO
      (MPD () -> IO (Response ())
forall a. MPD a -> IO (Response a)
withMPD (MPD () -> IO (Response ())) -> MPD () -> IO (Response ())
forall a b. (a -> b) -> a -> b
$ PlaylistName -> Path -> MPD ()
forall (m :: * -> *). MonadMPD m => PlaylistName -> Path -> m ()
MPD.playlistAdd (String -> PlaylistName
forall a. IsString a => String -> a
fromString String
pl) Path
sel
      )
    )
    Vector Path
songPaths
  HState -> EventM n HState
forall (m :: * -> *). MonadIO m => HState -> m HState
rebuildPl HState
s