001/*
002 * SPDX-License-Identifier: Apache-2.0
003 *
004 * Copyright 2025-2026 The Enola <https://enola.dev> Authors
005 *
006 * Licensed under the Apache License, Version 2.0 (the "License");
007 * you may not use this file except in compliance with the License.
008 * You may obtain a copy of the License at
009 *
010 *     https://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package dev.enola.tool.todo.yaml;
019
020import dev.enola.common.collect.MoreIterables;
021import dev.enola.common.io.object.ObjectReaderWriter;
022import dev.enola.common.io.object.jackson.JacksonObjectReaderWriterChain;
023import dev.enola.common.io.resource.Resource;
024import dev.enola.tool.todo.ToDo;
025import dev.enola.tool.todo.ToDoRepository;
026import dev.enola.tool.todo.ToDoRepositoryInMemory;
027
028import java.io.IOException;
029import java.net.URI;
030import java.nio.file.NoSuchFileException;
031
032public class ToDoYamlFileRepository implements ToDoRepository {
033
034    private final ToDoRepository delegate = new ToDoRepositoryInMemory();
035    private final ObjectReaderWriter readerWriter;
036    private final Resource resource;
037
038    public ToDoYamlFileRepository(Resource resource) throws IOException {
039        this.readerWriter = new JacksonObjectReaderWriterChain();
040        this.resource = resource;
041
042        try {
043            MoreIterables.forEach(readerWriter.readArray(resource, ToDo.class), delegate::store);
044        } catch (NoSuchFileException e) {
045            // That's OK; we will create the file on first write.
046        }
047    }
048
049    private void write() throws IOException {
050        var tasks = delegate.list();
051        if (!readerWriter.write(tasks, resource)) {
052            throw new IOException("Failed to write ToDos to " + resource);
053        }
054    }
055
056    @Override
057    public ToDo get(URI id) {
058        return delegate.get(id);
059    }
060
061    @Override
062    public Iterable<ToDo> list() {
063        return delegate.list();
064    }
065
066    @Override
067    public void store(ToDo todo) throws IOException {
068        delegate.store(todo);
069        write();
070    }
071
072    @Override
073    public void delete(URI id) throws IOException {
074        delegate.delete(id);
075        write();
076    }
077}