// SPDX-FileCopyrightText: © 2021 Matthias Andreas Benkard <code@mail.matthias.benkard.de>
//
// SPDX-License-Identifier: LGPL-3.0-or-later

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.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.Channels;
import java.util.ArrayList;
import java.util.List;
import org.tukaani.xz.LZMA2Options;
import org.tukaani.xz.XZInputStream;
import org.tukaani.xz.XZOutputStream;

/**
 * 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 decompress(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 IllegalStateException(e);
        }
      }
      default -> throw new IllegalArgumentException(
          "unrecognized compression byte '%d'".formatted(compressionByte));
    };
  }

  private static ByteBuffer compress(ByteBuffer dataSlice) {
    var dataBytes = new byte[dataSlice.limit()];
    dataSlice.get(dataBytes);
    var compressedOutputStream = new ByteArrayOutputStream();

    byte compressionByte = 'x';
    compressedOutputStream.write(compressionByte);

    try (var compressingOutputStream =
            new XZOutputStream(compressedOutputStream, new LZMA2Options());
        var compressingChannel = Channels.newChannel(compressingOutputStream)) {
      compressingChannel.write(dataSlice);
      compressingOutputStream.write(dataBytes);
    } catch (IOException e) {
      // impossible
      throw new IllegalStateException(e);
    }

    var compressedBytes = compressedOutputStream.toByteArray();
    return ByteBuffer.wrap(compressedBytes);
  }

  private static byte[] serializeDeltaOperationList(List<DeltaOperation> deltaOperations) {
    var output = new ByteArrayOutputStream();

    for (var currentOperation : deltaOperations) {
      currentOperation.writeTo(output);
    }

    return output.toByteArray();
  }

  private static List<DeltaOperation> parseDeltaOperationList(
      byte[] bytes, List<ObjectType> objectTypes) {
    List<DeltaOperation> deltaOperations = new ArrayList<>();
    var byteBuffer = ByteBuffer.wrap(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(),
            Decoder.ofByteArray()
                .map(
                    bytes -> parseDeltaOperationList(bytes, objectTypes),
                    DeltaPartPayload::serializeDeltaOperationList))
        .contramap(DeltaPartPayload::decompress, DeltaPartPayload::compress);
  }
}
