package eu.mulk.jgvariant.ostree;

import eu.mulk.jgvariant.core.Decoder;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.List;
import org.tukaani.xz.XZInputStream;

/**
 * A payload file from a static delta.
 *
 * <p>The first byte is a compression byte: {@code 0} for none, {@code 'x'} for LZMA. The actual
 * GVariant data begins right after.
 *
 * <p>Reference: {@code
 * ostree-repo-static-delta-private.h#OSTREE_STATIC_DELTA_PART_PAYLOAD_FORMAT_V0}
 *
 * @param fileModes the {@link FileMode}s of the files generated by this delta payload.
 * @param xattrs the {@link Xattr}s of the files generated by this delta payload.
 * @param rawDataSource the data bytes used in the delta operations.
 * @param operations the operations to apply during delta patching.
 * @see DeltaSuperblock
 */
public record DeltaPartPayload(
    List<FileMode> fileModes,
    List<List<Xattr>> xattrs,
    ByteString rawDataSource,
    List<DeltaOperation> operations) {

  private static ByteBuffer preparse(ByteBuffer byteBuffer) {
    byte compressionByte = byteBuffer.get(0);
    var dataSlice = byteBuffer.slice(1, byteBuffer.limit() - 1);
    return switch (compressionByte) {
      case 0 -> dataSlice;
      case (byte) 'x' -> {
        try {
          var dataBytes = new byte[dataSlice.limit()];
          dataSlice.get(dataBytes);
          var decompressingInputStream = new XZInputStream(new ByteArrayInputStream(dataBytes));

          var decompressedOutputStream = new ByteArrayOutputStream();
          decompressingInputStream.transferTo(decompressedOutputStream);

          yield ByteBuffer.wrap(decompressedOutputStream.toByteArray());
        } catch (IOException e) {
          // impossible
          throw new UncheckedIOException(e);
        }
      }
      default -> throw new IllegalArgumentException(
          "unrecognized compression byte '%d'".formatted(compressionByte));
    };
  }

  private static List<DeltaOperation> parseDeltaOperationList(
      ByteString byteString, List<ObjectType> objectTypes) {
    List<DeltaOperation> deltaOperations = new ArrayList<>();
    var byteBuffer = ByteBuffer.wrap(byteString.bytes());
    int objectIndex = 0;

    while (byteBuffer.hasRemaining()) {
      var currentOperation = DeltaOperation.readFrom(byteBuffer, objectTypes.get(objectIndex));
      deltaOperations.add(currentOperation);
      if (currentOperation instanceof DeltaOperation.Close
          || currentOperation instanceof DeltaOperation.OpenSpliceAndCloseMeta
          || currentOperation instanceof DeltaOperation.OpenSpliceAndCloseReal) {
        ++objectIndex;
      }
    }

    return deltaOperations;
  }

  /**
   * A file mode triple (UID, GID, and permission bits).
   *
   * @param uid the user ID that owns the file.
   * @param gid the group ID that owns the file.
   * @param mode the POSIX permission bits.
   */
  public record FileMode(int uid, int gid, int mode) {

    private static final Decoder<FileMode> DECODER =
        Decoder.ofStructure(
            FileMode.class,
            Decoder.ofInt().withByteOrder(ByteOrder.BIG_ENDIAN),
            Decoder.ofInt().withByteOrder(ByteOrder.BIG_ENDIAN),
            Decoder.ofInt().withByteOrder(ByteOrder.BIG_ENDIAN));

    /**
     * Acquires a {@link Decoder} for the enclosing type.
     *
     * @return a possibly shared {@link Decoder}.
     */
    public static Decoder<FileMode> decoder() {
      return DECODER;
    }
  }

  /**
   * Acquires a {@link Decoder} for the enclosing type.
   *
   * @return a possibly shared {@link Decoder}.
   */
  public static Decoder<DeltaPartPayload> decoder(DeltaMetaEntry deltaMetaEntry) {
    var objectTypes =
        deltaMetaEntry.objects().stream().map(DeltaMetaEntry.DeltaObject::objectType).toList();
    return Decoder.ofStructure(
            DeltaPartPayload.class,
            Decoder.ofArray(FileMode.decoder()),
            Decoder.ofArray(Decoder.ofArray(Xattr.decoder())),
            ByteString.decoder(),
            ByteString.decoder()
                .map(byteString -> parseDeltaOperationList(byteString, objectTypes)))
        .contramap(DeltaPartPayload::preparse);
  }
}
