module CellularFluid.Grid.Parse where

import           RIO
import qualified RIO.Vector               as V

import           Data.Attoparsec.Text

import           CellularFluid.Grid.Types

data GridCfg =
  GridCfg
    { width     :: Int
    , height    :: Int
    , size      :: Double
    , density   :: Double
    , viscosity :: Double
    }

parseGrid :: Text -> Either String (Grid, PhysCfg)
parseGrid = parseOnly gridParser

gridParser :: Parser (Grid, PhysCfg)
gridParser = do
  cfg <- pGridCfg
  cells <- pGridCells cfg
  let grid =
        Grid {gridCells = cells, gridWidth = width cfg, gridHeight = height cfg}
      phys =
        PhysCfg
          { phyGridSize = size cfg
          , phyFDRho = density cfg
          , phyFDMu = viscosity cfg
          }
  return (grid, phys)

pGridCfg :: Parser GridCfg
pGridCfg = do
  width <- decimal
  many1 space
  height <- decimal
  many1 space
  size <- double
  many1 space
  density <- double
  many1 space
  viscosity <- double
  endOfLine <?> "Too many arguments on first line"
  return $ GridCfg {..}

pGridCells :: GridCfg -> Parser (Vector Cell)
pGridCells _ = do
  cs <- pCell `sepBy1` space
  return $ V.fromList cs

pCell :: Parser Cell
pCell = pFluidD <|> pWall

pFluidD, pWall :: Parser Cell
pFluidD = do
  string "FD" -- Diffusive Fluid
  many1 space
  p <- double
  return $ FluidD p

pWall = string "W" >> return Wall
