// Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.dex;

import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import javax.imageio.ImageIO;
import org.apache.commons.compress.compressors.CompressorException;
import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream;

public class BSPatch {

  private final static char[] BSDIFF_MAGIC = "BSDIFF40".toCharArray();
  private final static int BSDIFF_HEADER_LENGTH = 32;

  private final ByteBuffer patchInput;
  private final ByteBuffer oldInput;
  private final Path output;
  private final Path dexPath;

  private InputStream controlStream;
  private InputStream diffStream;
  private InputStream extraStream;

  private long controlBytesRead;
  private long diffBytesRead;
  private long extraBytesRead;
  private int controlBlockLen;
  private int diffBlockLen;
  private int extraBlockLen;

  public static void main(String[] args) {
    boolean imageMode = args.length > 1 && args[0].equals("-i");
    int argOffset = imageMode ? 1 : 0;
    if (args.length < argOffset + 3) {
      System.out.println("Usage: [-i] <patch file> <original dex> <output file> [target dex]");
      System.exit(1);
    }
    try {
      new BSPatch(Paths.get(args[argOffset]), Paths.get(args[argOffset + 1]),
          Paths.get(args[argOffset + 2]),
          args.length != argOffset + 4 ? null : Paths.get(args[argOffset + 3]))
          .apply(imageMode);
    } catch (IOException e) {
      System.err.println("File I/O error: " + e.toString());
    } catch (CompressorException e) {
      System.err.println("BZIP error: " + e.toString());
    }
  }

  private BSPatch(Path patchInput, Path oldInput, Path output, Path dexPath) throws IOException {
    this.patchInput = ByteBuffer.wrap(Files.readAllBytes(patchInput));
    this.oldInput = ByteBuffer.wrap(Files.readAllBytes(oldInput));
    this.output = output;
    this.dexPath = dexPath;
  }

  public void apply(boolean imageMode) throws CompressorException, IOException {
    PatchExecutor executor = imageMode ? new ImageExecutor(dexPath) : new FileExecutor();
    checkHeader();
    setupSegmentsAndOutput(executor);
    processControl(executor);
    executor.writeResult();
    printStats();
  }

  private int percentOf(long a, long b) {
    return (int) ((((double) a) / ((double) b)) * 100);
  }

  private void printStats() {
    System.out.println("Size of control block (compressed bytes): " + controlBlockLen);
    System.out.println("Size of control block (read bytes): " + controlBytesRead);
    System.out
        .println("Compression of control block: " + percentOf(controlBlockLen, controlBytesRead));
    System.out.println("Size of diff data block (compressed bytes): " + diffBlockLen);
    System.out.println("Size of diff data block (read bytes): " + diffBytesRead);
    System.out
        .println("Compression of diff data block: " + percentOf(diffBlockLen, diffBytesRead));
    System.out.println("Size of extra data block (compressed bytes): " + extraBlockLen);
    System.out.println("Size of extra data block (read bytes): " + extraBytesRead);
    System.out
        .println("Compression of extra data block: " + percentOf(extraBlockLen, extraBytesRead));
  }

  private void processControl(PatchExecutor executor) throws IOException {
    int blockSize;
    while ((blockSize = readNextControlEntry()) != Integer.MIN_VALUE) {
      int extraSize = readNextControlEntry();
      int advanceOld = readNextControlEntry();
      executor.copyDiff(blockSize);
      executor.copyOld(blockSize);
      executor.submitBlock(blockSize);
      executor.copyExtra(extraSize);
      executor.skipOld(advanceOld);
    }
  }

  private void checkHeader() {
    for (int i = 0; i < BSDIFF_MAGIC.length; i++) {
      if (patchInput.get() != BSDIFF_MAGIC[i]) {
        throw new RuntimeException("Illegal patch, wrong magic!");
      }
    }
  }

  private void setupSegmentsAndOutput(PatchExecutor executor)
      throws CompressorException, IOException {
    controlBlockLen = readOffset();
    diffBlockLen = readOffset();
    int newFileSize = readOffset();

    extraBlockLen =
        patchInput.array().length - (BSDIFF_HEADER_LENGTH + controlBlockLen + diffBlockLen);

    executor.createOutput(newFileSize);
    controlStream = new BZip2CompressorInputStream(
        new ByteArrayInputStream(patchInput.array(), BSDIFF_HEADER_LENGTH, controlBlockLen));
    diffStream = new BZip2CompressorInputStream(
        new ByteArrayInputStream(patchInput.array(), BSDIFF_HEADER_LENGTH + controlBlockLen,
            diffBlockLen));
    extraStream = new BZip2CompressorInputStream(
        new ByteArrayInputStream(patchInput.array(),
            BSDIFF_HEADER_LENGTH + controlBlockLen + diffBlockLen,
            extraBlockLen));
  }

  private int readOffset() {
    byte[] buffer = new byte[8];
    patchInput.get(buffer);
    return decodeOffset(buffer);
  }

  private int readNextControlEntry() throws IOException {
    byte[] buffer = new byte[8];
    int read = controlStream.read(buffer);
    if (read == -1) {
      return Integer.MIN_VALUE;
    }
    controlBytesRead += read;
    assert read == buffer.length;
    return decodeOffset(buffer);
  }

  private static int decodeOffset(byte[] buffer) {
    long offset = buffer[7] & 0x7F;
    for (int i = 6; i >= 0; i--) {
      offset = (offset << 8) | (((int) buffer[i]) & 0xff);
    }
    if ((buffer[7] & 0x80) != 0) {
      offset = -offset;
    }
    assert offset < Integer.MAX_VALUE && offset > Integer.MIN_VALUE;
    return (int) offset;
  }

  private static abstract class PatchExecutor {

    public abstract void createOutput(int newFileSize);

    public abstract void copyDiff(int blockSize) throws IOException;

    public abstract void copyOld(int blockSize) throws IOException;

    public abstract void submitBlock(int blockSize);

    public abstract void copyExtra(int extraSize) throws IOException;

    public abstract void skipOld(int advanceOld) throws IOException;

    public abstract void writeResult() throws IOException;
  }

  private class FileExecutor extends PatchExecutor {

    private ByteBuffer resultBuffer;
    private byte[] mergeBuffer = null;

    @Override
    public void createOutput(int newFileSize) {
      resultBuffer = ByteBuffer.allocate(newFileSize);
    }

    @Override
    public void copyDiff(int blockSize) throws IOException {
      assert mergeBuffer == null;
      mergeBuffer = new byte[blockSize];
      int read = diffStream.read(mergeBuffer);
      diffBytesRead += read;
      assert read == blockSize;
    }

    @Override
    public void copyOld(int blockSize) throws IOException {
      assert mergeBuffer.length == blockSize;
      byte[] data = new byte[blockSize];
      oldInput.get(data);
      for (int i = 0; i < mergeBuffer.length; i++) {
        mergeBuffer[i] = (byte) ((((int) mergeBuffer[i]) & 0xff) + (((int) data[i]) & 0xff));
      }
    }

    @Override
    public void submitBlock(int blockSize) {
      assert mergeBuffer != null;
      assert mergeBuffer.length == blockSize;
      resultBuffer.put(mergeBuffer);
      mergeBuffer = null;
    }

    @Override
    public void copyExtra(int extraSize) throws IOException {
      byte[] data = new byte[extraSize];
      int read = extraStream.read(data);
      assert read == extraSize;
      extraBytesRead += read;
      resultBuffer.put(data);
    }

    @Override
    public void skipOld(int delta) throws IOException {
      oldInput.position(oldInput.position() + delta);
    }

    @Override
    public void writeResult() throws IOException {
      OutputStream outputStream = Files.newOutputStream(output);
      outputStream.write(resultBuffer.array());
      outputStream.close();
    }
  }

  private class ImageExecutor extends PatchExecutor {

    private final Path dexPath;

    BufferedImage image;
    int position = 0;
    int width;
    int height;

    private ImageExecutor(Path dexPath) {
      this.dexPath = dexPath;
    }

    @Override
    public void createOutput(int newFileSize) {
      int root = (int) Math.sqrt(newFileSize);
      width = newFileSize / root;
      height = newFileSize / width + 1;
      image = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
    }

    @Override
    public void copyDiff(int blockSize) throws IOException {
      byte[] buffer = new byte[blockSize];
      int read = diffStream.read(buffer);
      assert read == blockSize;
      diffBytesRead += read;
      for (int i = 0; i < buffer.length; i++) {
        if (buffer[i] != 0) {
          int y = (position + i) / width;
          int x = (position + i) % width;
          int rgb = image.getRGB(x, y);
          rgb = rgb | 0xFF0000;
          image.setRGB(x, y, rgb);
        }
      }
    }

    @Override
    public void copyOld(int blockSize) throws IOException {
      for (int i = 0; i < blockSize; i++) {
        int y = (position + i) / width;
        int x = (position + i) % width;
        int rgb = image.getRGB(x, y);
        if ((rgb & 0xFF0000) == 0) {
          rgb = rgb | 0xFF00;
        }
        image.setRGB(x, y, rgb);
      }
    }

    @Override
    public void submitBlock(int blockSize) {
      position += blockSize;
    }

    @Override
    public void copyExtra(int extraSize) throws IOException {
      long skipped = extraStream.skip(extraSize);
      assert skipped == extraSize;
      extraBytesRead += skipped;
      for (int i = 0; i < extraSize; i++) {
        int y = (position + i) / width;
        int x = (position + i) % width;
        int rgb = image.getRGB(x, y);
        rgb = rgb | 0xFF;
        image.setRGB(x, y, rgb);
      }
      position += extraSize;
    }

    @Override
    public void skipOld(int advanceOld) throws IOException {
    }

    @Override
    public void writeResult() throws IOException {
      if (dexPath != null) {
        DexSection[] sections = DexParser.parseMapFrom(dexPath);
        for (DexSection section : sections) {
          int y = section.offset / width;
          for (int x = 0; x < width; x++) {
            int val = (x / 10) % 2 == 0 ? 0 : 0xffffff;
            image.setRGB(x, y, val);
          }
          System.out.println(section);
        }
      }
      ImageIO.write(image, "png", output.toFile());
    }
  }
}
