-- | Tries to load a particular model from the cache or by loading it from
--   the filesystem (looking in the specified paths) and parsing it. The
--   parse may recursively load further models.
loadL2ModelFromURL' :: [String] -> String -> LookupModel L2.L2Model
loadL2ModelFromURL' incl mpath = do
  -- Try to find the model first...
  maybe (fail $ "Could not find model " ++ mpath ++ " anywhere in the include paths " ++ show incl) return =<< (
    firstJustM $ flip map incl $ \tryIncl -> do
      let fullPath = tryIncl ++ mpath
      alreadyLoaded <- M.lookup (BSC.pack fullPath) <$> get
      case alreadyLoaded of
        Just m -> return $ Just m
        Nothing -> do
          (r, v) <- liftIO $ curlGetString_ (tryIncl ++ mpath) []
          if r == CurlOK
            then do
              nsc <- LookupModel . lift . ErrorT $ return (parseFieldML mpath v)
              finalImpMap <- tryResolveAllImports incl nsc
              mod <- LookupModel . lift $ translateL1ToL2 mpath nsc finalImpMap
              modify (M.insert (BSC.pack fullPath) mod)
              return $ Just mod
            else
              return Nothing)

-- | Attempts to load all imports mentioned in a L1 model.
loadL2ModelFromURL' :: [String] -> String -> LookupModel L2.L2Model
loadL2ModelFromURL' incl mpath = do
  -- Try to find the model first...
  maybe (fail $ "Could not find model " ++ mpath ++ " anywhere in the include paths " ++ show incl) return =<< (
    firstJustM $ flip map incl $ \tryIncl -> do
      let fullPath = tryIncl ++ mpath
      alreadyLoaded <- M.lookup (BSC.pack fullPath) <$> get
      case alreadyLoaded of
        Just m -> return $ Just m
        Nothing -> do
          (r, v) <- liftIO $ curlGetString_ (tryIncl ++ mpath) []
          if r == CurlOK
            then do
              nsc <- LookupModel . lift . ErrorT $ return (parseFieldML mpath v)
              finalImpMap <- tryResolveAllImports incl nsc
              mod <- LookupModel . lift $ translateL1ToL2 mpath nsc finalImpMap
              modify (M.insert (BSC.pack fullPath) mod)
              return $ Just mod
            else
              return Nothing)

-- | Attempts to load all imports mentioned in a L1 model.
loadL2ModelFromURL' incl mpath = do
  -- Try to find the model first...
  maybe (fail $ "Could not find model " ++ mpath ++ " anywhere in the include paths " ++ show incl) return =<< (
    firstJustM $ flip map incl $ \tryIncl -> do
      let fullPath = tryIncl ++ mpath
      alreadyLoaded <- M.lookup (BSC.pack fullPath) <$> get
      case alreadyLoaded of
        Just m -> return $ Just m
        Nothing -> do
          (r, v) <- liftIO $ curlGetString_ (tryIncl ++ mpath) []
          if r == CurlOK
            then do
              nsc <- LookupModel . lift . ErrorT $ return (parseFieldML mpath v)
              finalImpMap <- tryResolveAllImports incl nsc
              mod <- LookupModel . lift $ translateL1ToL2 mpath nsc finalImpMap
              modify (M.insert (BSC.pack fullPath) mod)
              return $ Just mod
            else
              return Nothing)

-- | Attempts to load all imports mentioned in a L1 model.