module WordChooser (
    Hand,
    buildWords,
    scoreCmp,
    sortWHPairs,
    wordsWithChar,
    scoreWord
) where

import Data.List (sortBy)
import Data.Maybe (fromJust, mapMaybe)
import Data.HashMap.Strict (member)
import qualified Data.Map as Map
import Types (Hand)
import Hand (playTile)

-- Define a map between letters and their inverted usage frequencies generated by ChatGPT.
letterPoints :: Map.Map Char Int
letterPoints = Map.fromList 
    [('a',6833),('b',13508),('c',12218),('d',10747),('e',2298),('f',12772),
     ('g',12985),('h',8906),('i',8034),('j',14847),('k',14228),('l',10975),
     ('m',12594),('n',8251),('o',7493),('p',13071),('q',14905),('r',9013),
     ('s',8673),('t',5944),('u',12242),('v',14022),('w',12640),('x',14850),
     ('y',13026),('z',14926)]

buildWord :: String -> Hand -> Maybe Hand
buildWord [] hand = Just hand
buildWord (w:ws) hand
    | null hand || not (member w hand) = Nothing
    | otherwise = buildWord ws $ playTile w hand

buildWords :: Hand -> [String] -> [(String, Hand)]
buildWords hand = mapMaybe bw_pair
    where
        bw_pair [_] = Nothing
        bw_pair word = case buildWord word hand of
            Nothing -> Nothing
            Just _hand -> Just (word, _hand)

scoreCmp :: String -> String -> Ordering
-- flip x and y so sort puts highest scorers first 
scoreCmp x y = scoreWord y `compare` scoreWord x

scoreWord :: String -> Int
scoreWord w = 15000 * length w 
    + sum (map scoreChar w)

scoreChar :: Char -> Int
scoreChar ' ' = 0
scoreChar c = fromJust $ Map.lookup c letterPoints

sortWHPairs :: [(String, Hand)] -> [(String, Hand)]
sortWHPairs = sortBy (\x y -> scoreCmp (fst x) (fst y))

wordsWithChar :: Char -> [String] -> [String]
wordsWithChar c = filter (elem c)