module Data.SMILES.Parser where

import           Text.Megaparsec
import           Text.Megaparsec.Lexer
import           Text.Megaparsec.Text

import           Data.SMILES
import           Data.SMILES.Atom.Parser
import           Data.SMILES.Bond.Parser

smilesP :: Parser SMILES
smilesP = do atom <- atomPackP
             rest <- concat <$> many chainPackP
             pure $ SMILES (atom ++ rest)

atomPackP :: Parser [ChainToken]
atomPackP = do atom <- Atom <$> atomP
               ringBonds <- many ringP
               branches <- many branchP
               pure $ (atom : ringBonds) ++ branches

chainPackP :: Parser [ChainToken]
chainPackP = do bondMb <- optional (Bond <$> bondP)
                atomPacks <- concat <$> some atomPackP
                rest <- concat <$> many chainPackP
                case bondMb of
                  Nothing   -> pure $ atomPacks ++ rest
                  Just bond -> pure $ bond : atomPacks ++ rest

branchP :: Parser ChainToken
branchP = Branch <$> between (char '(') (char ')') (SMILES <$> chainPackP)

ringP :: Parser ChainToken
ringP = RingClosure <$> ringHelperP
  where ringHelperP :: Parser Int
        ringHelperP = do pcMb <- optional $ char '%'
                         case pcMb of
                           Just _  -> fromIntegral <$> integer
                           Nothing -> read . pure <$> digitChar