
import Data.List (intercalate)
import Data.Maybe (catMaybes)
import Database.HDBC
import Database.HDBC.Sqlite3
import System (getArgs)

-- "foo" -> [('f', 1), ('o', 2)]
count [] = []
count (x:xs) = count' xs x 1
    where count' [] cur n = [(cur, n)]
          count' (x:xs) cur n
              | x == cur  = count' xs cur (n + 1)
              | otherwise = (cur, n) : count' xs x 1

prop_count_total xs = length xs == (sum . map snd . count $ xs)
    -- so that QC doesn't use [()]
    where types = xs :: [Bool]

listCategories conn = do
    st <- prepare conn "SELECT category FROM category ORDER BY category"
    execute st []
    rows <- sFetchAllRows st
    mapM_ (putStrLn . uncurry format) . count . catMaybes . concat $ rows
        where format category count = category ++ " (" ++ show count ++ ")"

categorySearch conn categories = do
    let titles = intercalate " INTERSECT " $
            map (const "SELECT title FROM category WHERE category = ?")
                categories
        query = "SELECT title FROM page WHERE title IN (" ++ titles ++ ")"
    st <- prepare conn query
    execute st (map SqlString categories)
    rows <- sFetchAllRows st
    mapM_ putStrLn $ catMaybes . concat $ rows

main = do
    args <- getArgs
    conn <- connectSqlite3 "cookbook.db"
    case args of
        [] -> listCategories conn
        _ -> categorySearch conn args

