package p.studio.workspaces.editor;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.ByteBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.CodingErrorAction;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Objects;
import java.util.Optional;

public final class EditorFileBufferLoader {

    public Optional<EditorOpenFileBuffer> load(final Path path) {
        final var normalizedPath = Objects.requireNonNull(path, "path").toAbsolutePath().normalize();
        if (!Files.isRegularFile(normalizedPath)) {
            return Optional.empty();
        }

        final byte[] bytes;
        try {
            bytes = Files.readAllBytes(normalizedPath);
        } catch (IOException ioException) {
            throw new UncheckedIOException(ioException);
        }

        if (containsNulByte(bytes)) {
            return Optional.empty();
        }

        final String content;
        try {
            content = StandardCharsets.UTF_8.newDecoder()
                    .onMalformedInput(CodingErrorAction.REPORT)
                    .onUnmappableCharacter(CodingErrorAction.REPORT)
                    .decode(ByteBuffer.wrap(bytes))
                    .toString();
        } catch (CharacterCodingException codingException) {
            return Optional.empty();
        }

        return Optional.of(new EditorOpenFileBuffer(
                normalizedPath,
                normalizedPath.getFileName().toString(),
                content,
                lineSeparator(content)));
    }

    private boolean containsNulByte(final byte[] bytes) {
        for (final byte value : bytes) {
            if (value == 0) {
                return true;
            }
        }
        return false;
    }

    private String lineSeparator(final String content) {
        return content.contains("\r\n") ? "CRLF" : "LF";
    }
}
