module Cookbook.Project.Quill.Quill2 where
import qualified Cookbook.Essential.Common as Cm
import qualified Cookbook.Essential.Continuous as Ct
import qualified Cookbook.Ingredients.Lists.Modify as Md
import qualified Cookbook.Ingredients.Lists.Access as Ac
import qualified Cookbook.Ingredients.Lists.Encompass as En
import qualified Cookbook.Ingredients.Tupples.Look as Lk
data Element a = List [a] | Table [(a,a)] deriving (Eq, Show)
type Quill = (String,Element String)
decomment :: String -> String
decomment = (`Ct.splice` ("/*", "*/"))
prepare :: [String] -> String
prepare = decomment . (`Ct.remove` '\n') . unlines
pTable :: String -> Quill
pTable x = typ
where
name = Md.between (Ct.before x '{') ('(',')')
typ = (name,if (Ct.before x '{') `Ac.contains` "table" then Table (parseTables body) else List body)
body = Md.splitOn (En.encompassing x ('{','}')) ';'
quoted y = if ('`','\'') `Ac.surrounds` y then En.encompassing x ('`','\'') else Ct.remove y ' '
parseTables [] = []
parseTables (x:xs) =(quoted $ Ct.before x ':', Ct.after x ':') : parseTables xs
pFile :: [String] -> [Quill]
pFile x = case allTables of
[] -> []
(y:ys) -> pTable y : pFile ys
where
prepared = prepare x
allTables = Md.splitOn prepared '}'
data QuillStatus = QuillSuccess Quill | QuillMissing | QuillMultiple deriving (Eq,Show)
getQuillName :: Quill -> String
getQuillName = fst
getQuill :: [Quill] -> String -> QuillStatus
getQuill [] _ = QuillMissing
getQuill (x:xs) c
| Ac.count (map getQuillName (x:xs)) c > 1 = QuillMultiple
| getQuillName x == c = QuillSuccess x
| otherwise = getQuill xs c
lookUp :: [Quill] -> (String, String) -> String
lookUp x (a,b) = case (getQuill x a) of
QuillMissing -> error $ "Table not found."
QuillMultiple -> error $ "Multiple values of " ++ a ++ " detected. Database eror, fix manually."
(QuillSuccess (c,d)) -> case d of
(List f) -> error "Cannot look up the value of a list."
(Table f) -> let c = Lk.lookList f b in if (c == []) then (error $ "Item " ++ b ++ " not found in table " ++ a) else (if (length c > 1) then multipleInnerError else (head c))
where multipleInnerError = error $ "Multiple values of " ++ b ++ " found in table " ++ a ++ ". Database corrupted, change manually."
removeQuill :: [Quill] -> String -> [Quill]
removeQuill [] _ = []
removeQuill ((x,y):xs) c
| x == c = removeQuill xs c
| otherwise = (x,y) : removeQuill xs c
removeItem :: [Quill] -> (String, String) -> [Quill]
removeItem x (a,b) = case (getQuill x a) of
QuillSuccess (c,j) -> case j of
(Table d) -> (c,(Table [(y,t) | (y,t) <- d, y /= b])) : (removeQuill x a)
(List d) -> (c,List $ Ct.remove d c) : removeQuill x a
_ -> (let l = lookUp x (a,b) in x)
addQuill :: [Quill] -> Quill -> [Quill]
addQuill x c = c : x
addToQuill :: Quill -> (String, String) -> Quill
addToQuill (x,b) c = case b of
(Table z) -> (x, Table (c:z))
(List z) -> (x, List (z))
addItem :: [Quill] -> (String, String, String) -> [Quill]
addItem x (a, b, c)= case getQuill x a of
QuillSuccess (y, ys) -> case ys of
(Table d) -> (y,Table $ (b,c) : d) : removeQuill x a
(List d) -> (y,List $ (c:d)) : removeQuill x a
QuillMultiple -> error "Multiple found"
QuillMissing -> error "Not found quill!"
changeItem :: [Quill] -> (String, String, String) -> [Quill]
changeItem x (a,b,c) = addItem (removeItem x (a,b)) (a,b,c)
toString :: Quill -> String
toString (nm,typ) = case typ of
(List a) -> ("list(" ++ nm ++ "){" ++ (Cm.flt (map (\c -> (c ++ ";")) a))) ++ "}"
(Table a) -> ("table(" ++ nm ++ "){" ++ (Cm.flt $ stringify a)) ++ "}"
where
stringify [] = []
stringify ((a,b):xs) = (a ++ ":" ++ b ++ ";") : stringify xs