package leigh.notek.store;

import leigh.mecha.log.MechaLogger;
import leigh.mecha.log.MechaLoggerFactory;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.time.Instant;
import java.util.List;
import java.util.function.Consumer;

public class ZettelFilesStore implements ZettelStore {
    private static final MechaLogger logger = MechaLoggerFactory.getLogger(ZettelFilesStore.class);
    private static final String EXTENSION = ".md";
    private final Path directory;

    public ZettelFilesStore(Path directory) {
        this.directory = directory;
    }

    public String newId() throws IOException {
        String id = Long.toString(Instant.now().toEpochMilli());
        File f = getZettelFile(id);
        // TODO: Handle this better
        if (f.exists()) throw new IllegalStateException();
        f.createNewFile();
        return id;
    }

    @Override
    public void delId(String id) {
        File f = getZettelFile(id);
        f.delete();
    }

    public void getIds(List<String> dst) throws IOException {
        Files.walk(directory).forEach(new Consumer<Path>() {
            @Override
            public void accept(Path path) {
                logger.debug("Scanning path: {}", path);
                // TODO Check if this is a regular file in case they name the dir that
                if (path.toString().endsWith(EXTENSION)) {
                    String fn = FilenameUtils.getBaseName(path.toString());
                    logger.debug("Found note: {}", fn);
                    dst.add(fn);
                }
            }
        });
    }

    private File getZettelFile(String id) {
        Path p = directory.resolve(id + EXTENSION);
        return p.toFile();
    }

    @Override
    public String getZettel(String id) throws IOException {
        File f = getZettelFile(id);
        if (f.exists() && f.isFile()) {
            try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(f))) {
                return IOUtils.toString(bis);
            }
        } else {
            logger.warn("Zettel did not exist or was not regular file. [fn: {}]", f.toString());
        }
        return null;
    }

    @Override
    public void setZettel(String id, String content) throws IOException {
        logger.info("Saving zettel. [id: {}] [content: {}}", id, content);
        File tmp = File.createTempFile("notek", ".md");
        try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(tmp))) {
            bos.write(content.getBytes(StandardCharsets.UTF_8));
        }
        File dst = getZettelFile(id);
        Files.move(tmp.toPath(), dst.toPath(), StandardCopyOption.REPLACE_EXISTING);
        logger.info("Saved. [tmp: {}] [fn: {}]", tmp, dst);
    }
}
