module Lib.Util

import Prelude
import Lib.Common
import Lib.Types
import Data.List1

-- pi arity is primitive functions
piArity : Tm -> Nat
piArity (Pi _ _ _ quant _ b) = S (piArity b)
piArity _ = Z

funArgs : Tm -> (Tm × List Tm)
funArgs tm = go tm Nil
  where
    go : Tm -> List Tm -> (Tm × List Tm)
    go (App _ t u) args = go t (u :: args)
    go t args = (t, args)

data Binder : U where
  MkBinder : FC -> String -> Icit -> Quant -> Tm -> Binder

-- I don't have a show for terms without a name list

instance Show Binder where
  show (MkBinder _ nm icit quant t) = "[\{show quant}\{nm} \{show icit} : ...]"

splitTele : Tm -> (Tm × List Binder)
splitTele = go Nil
  where
    go : List Binder -> Tm -> (Tm × List Binder)
    go ts (Pi fc nm icit quant t u) = go (MkBinder fc nm icit quant t :: ts) u
    go ts tm = (tm, reverse ts)



getBaseDir : String → FC → String → M (String × QName)
getBaseDir fn fc modName = do
  let (path, modName') = unsnoc $ split1 modName "."
  let parts = split1 fn "/"
  let (dirs,file) = unsnoc parts
  let (name, ext) = splitFileName file

  let parts = split1 fn "/"
  let (dirs,file) = unsnoc parts
  let (path, modName') = unsnoc $ split1 modName "."
  unless (modName' == name) $ \ _ => error fc "module name \{modName'} doesn't match \{name}"
  let (Right base) = baseDir (Lin <>< dirs) (Lin <>< path)
    | Left err => error fc err
  let base = if base == "" then "." else base
  pure (base, QN path modName')
  where
    baseDir : SnocList String -> SnocList String -> Either String String
    baseDir dirs Lin = Right $ joinBy "/" (dirs <>> Nil)
    baseDir (dirs :< d) (ns :< n) = if d == n
      then baseDir dirs ns
      else Left "module path doesn't match directory"
    baseDir Lin _ = Left "module path doesn't match directory"
