-- Copyright 2023 Evan Laforge
-- This program is distributed under the terms of the GNU General Public
-- License 3.0, see COPYING or http://www.gnu.org/licenses/gpl-3.0.txt

module Solkattu.Talas where
import qualified Data.Set as Set
import qualified GHC.Generics as Generics

import qualified Util.Num as Num
import qualified Util.Pretty as Pretty
import qualified Solkattu.Tala as Tala

import           Global


data Tala = Carnatic Tala.Tala | Hindustani Tal
    deriving (Tala -> Tala -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Tala -> Tala -> Bool
$c/= :: Tala -> Tala -> Bool
== :: Tala -> Tala -> Bool
$c== :: Tala -> Tala -> Bool
Eq, Akshara -> Tala -> ShowS
[Tala] -> ShowS
Tala -> String
forall a.
(Akshara -> a -> ShowS)
-> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Tala] -> ShowS
$cshowList :: [Tala] -> ShowS
show :: Tala -> String
$cshow :: Tala -> String
showsPrec :: Akshara -> Tala -> ShowS
$cshowsPrec :: Akshara -> Tala -> ShowS
Show)

instance Pretty Tala where
    format :: Tala -> Doc
format = \case
        Carnatic Tala
tala -> forall a. Pretty a => a -> Doc
Pretty.format Tala
tala
        Hindustani Tal
tala -> forall a. Pretty a => a -> Doc
Pretty.format Tal
tala

aksharas :: Tala -> Tala.Akshara
aksharas :: Tala -> Akshara
aksharas = \case
    Carnatic Tala
tala -> Tala -> Akshara
Tala.tala_aksharas Tala
tala
    Hindustani Tal
tala -> Tal -> Akshara
talAksharas Tal
tala

angas :: Tala -> [Tala.Akshara]
angas :: Tala -> [Akshara]
angas = \case
    Carnatic Tala
tala -> Tala -> [Akshara]
Tala.tala_angas Tala
tala
    Hindustani Tal
tala -> forall a b. (a -> b) -> [a] -> [b]
map forall a b. (a, b) -> b
snd (Tal -> [(Tali, Akshara)]
talVibhags Tal
tala)

name :: Tala -> Text
name :: Tala -> Text
name = \case
    Carnatic Tala
tala -> Tala -> Text
Tala._name Tala
tala
    Hindustani Tal
tala -> Tal -> Text
talName Tal
tala

angaSet :: Tala -> Set Tala.Akshara
angaSet :: Tala -> Set Akshara
angaSet = forall a. Ord a => [a] -> Set a
Set.fromList forall b c a. (b -> c) -> (a -> b) -> a -> c
.  forall b a. (b -> a -> b) -> b -> [a] -> [b]
scanl forall a. Num a => a -> a -> a
(+) Akshara
0 forall b c a. (b -> c) -> (a -> b) -> a -> c
. Tala -> [Akshara]
angas

labels :: Tala -> [Text]
labels :: Tala -> [Text]
labels = \case
    Carnatic Tala
tala -> Tala -> [Text]
Tala.tala_labels Tala
tala
    Hindustani Tal
tala -> Tal -> [Text]
talLabels Tal
tala

-- * Tal

-- TODO I wound up using Carnatic Tala because I wound up using Korvai, but
-- I'll need some way to reconcile.
data Tal = Tal {
    Tal -> Text
talName :: Text
    , Tal -> [(Tali, Akshara)]
talVibhags :: [(Tali, Tala.Akshara)]
    } deriving (Tal -> Tal -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Tal -> Tal -> Bool
$c/= :: Tal -> Tal -> Bool
== :: Tal -> Tal -> Bool
$c== :: Tal -> Tal -> Bool
Eq, Akshara -> Tal -> ShowS
[Tal] -> ShowS
Tal -> String
forall a.
(Akshara -> a -> ShowS)
-> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Tal] -> ShowS
$cshowList :: [Tal] -> ShowS
show :: Tal -> String
$cshow :: Tal -> String
showsPrec :: Akshara -> Tal -> ShowS
$cshowsPrec :: Akshara -> Tal -> ShowS
Show, forall x. Rep Tal x -> Tal
forall x. Tal -> Rep Tal x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Tal x -> Tal
$cfrom :: forall x. Tal -> Rep Tal x
Generics.Generic)

instance Pretty Tal where
    format :: Tal -> Doc
format = forall a. (PrettyG (Rep a), Generic a) => a -> Doc
Pretty.formatGCamel

talAksharas :: Tal -> Tala.Akshara
talAksharas :: Tal -> Akshara
talAksharas = forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
Num.sum forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map forall a b. (a, b) -> b
snd forall b c a. (b -> c) -> (a -> b) -> a -> c
. Tal -> [(Tali, Akshara)]
talVibhags

talLabels :: Tal -> [Text]
talLabels :: Tal -> [Text]
talLabels = [(Tali, Akshara)] -> [Text]
taliLabels forall b c a. (b -> c) -> (a -> b) -> a -> c
. Tal -> [(Tali, Akshara)]
talVibhags

-- 1x 2 3 4 5x 6 7 8 9o 10 11 12 13x 14 15 16
taliLabels :: [(Tali, Tala.Akshara)] -> [Text]
taliLabels :: [(Tali, Akshara)] -> [Text]
taliLabels = forall a b. (a -> b) -> [a] -> [b]
map forall {a}. Show a => (a, Maybe Tali) -> Text
fmt forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. [a] -> [b] -> [(a, b)]
zip [Integer
1 ..] forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap forall {a}. (a, Akshara) -> [Maybe a]
expand
    where
    fmt :: (a, Maybe Tali) -> Text
fmt (a
n, Maybe Tali
mb_tali) = forall a. Show a => a -> Text
showt a
n forall a. Semigroup a => a -> a -> a
<> case Maybe Tali
mb_tali of
        Maybe Tali
Nothing -> Text
""
        Just Tali
Tali -> Text
"x"
        Just Tali
Kali -> Text
"o"
    expand :: (a, Akshara) -> [Maybe a]
expand (a
tali, Akshara
aksharas) = forall a. a -> Maybe a
Just a
tali forall a. a -> [a] -> [a]
: forall a. Akshara -> a -> [a]
replicate (Akshara
aksharas forall a. Num a => a -> a -> a
- Akshara
1) forall a. Maybe a
Nothing

data Tali = Tali | Kali
    deriving (Tali -> Tali -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Tali -> Tali -> Bool
$c/= :: Tali -> Tali -> Bool
== :: Tali -> Tali -> Bool
$c== :: Tali -> Tali -> Bool
Eq, Akshara -> Tali -> ShowS
[Tali] -> ShowS
Tali -> String
forall a.
(Akshara -> a -> ShowS)
-> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Tali] -> ShowS
$cshowList :: [Tali] -> ShowS
show :: Tali -> String
$cshow :: Tali -> String
showsPrec :: Akshara -> Tali -> ShowS
$cshowsPrec :: Akshara -> Tali -> ShowS
Show)
instance Pretty Tali where pretty :: Tali -> Text
pretty = forall a. Show a => a -> Text
showt

tintal :: Tal
tintal :: Tal
tintal = Text -> [(Tali, Akshara)] -> Tal
Tal Text
"tintal" [(Tali
Tali, Akshara
4), (Tali
Tali, Akshara
4), (Tali
Kali, Akshara
4), (Tali
Tali, Akshara
4)]

kehrwa :: Tal
kehrwa :: Tal
kehrwa = Text -> [(Tali, Akshara)] -> Tal
Tal Text
"kehrwa" [(Tali
Tali, Akshara
4), (Tali
Kali, Akshara
4)]

jhaptal :: Tal
jhaptal :: Tal
jhaptal = Text -> [(Tali, Akshara)] -> Tal
Tal Text
"jhaptal" [(Tali
Tali, Akshara
2), (Tali
Tali, Akshara
3), (Tali
Kali, Akshara
2), (Tali
Tali, Akshara
3)]

rupak :: Tal
rupak :: Tal
rupak = Text -> [(Tali, Akshara)] -> Tal
Tal Text
"rupak" [(Tali
Kali, Akshara
3), (Tali
Tali, Akshara
2), (Tali
Tali, Akshara
2)]