
final class ModelLoader {

    let content: Content

    let storage: Storage

    let context: LoadingContext

    init(content: Content, storage: Storage) {
        self.content = content
        self.storage = storage
        self.context = .init(content: content)
    }

    func load() -> LoadingResult {
        loadInternal()
        return context.results()
    }

    private func loadInternal() {
        guard storage.contentScope != nil else {
            context.error("Storage not initialized, not loading content")
            return
        }

        loadFiles()
        loadTags()
        loadPages()
        loadPosts()
        loadSettings()
    }

    private func loadFiles() {
        guard let files = storage.loadAllFiles() else {
            context.error("Failed to load file list")
            return
        }
        if files.isEmpty { print("No files loaded") }

        files.forEach { (fileId, data) in
            let fileData = data.data
            let isExternal = data.isExternal
            context.files[fileId] = FileResource(content: content, id: fileId, data: fileData, isExternalFile: isExternal)
        }
    }

    private func loadTags() {
        guard let tags = storage.loadAllTags() else {
            context.error("Failed to load file tags")
            return
        }
        if tags.isEmpty { print("No tags loaded") }

        tags.forEach { (tagId, data) in
            context.tags[tagId] = Tag(context: context, id: tagId, data: data)
        }
    }

    private func loadPages() {
        guard let pages = storage.loadAllPages() else {
            context.error("Failed to load file pages")
            return
        }
        if pages.isEmpty { print("No pages loaded") }

        pages.forEach { pageId, data in
            let page = Page(context: context, id: pageId, data: data)
            page.updateContentExistence()
            context.pages[pageId] = page
        }
    }

    private func loadPosts() {
        guard let posts = storage.loadAllPosts() else {
            context.error("Failed to load file posts")
            return
        }
        if posts.isEmpty { print("No posts loaded") }

        posts.forEach { postId, data in
            context.posts[postId] = Post(context: context, id: postId, data: data)
        }
    }

    private func loadSettings() {
        guard let settings = storage.loadSettings() else {
            context.error("Failed to load settings")
            return
        }

        context.tagOverview = settings.tagOverview.map { data in
            TagOverview(context: context, id: "all-tags", data: data)
        }

        context.settings = Settings(context: context, data: settings)
    }
}
