package info.knacki.pass.git.entities;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.zip.DeflaterOutputStream;

public class GitPackableUtil {
    public static byte getObjType(GitPackable.eType type) {
        switch (type) {
            case eType_Commit:
                return 1;
            case eType_Tree:
                return 2;
            case eType_Blob:
                return 3;
            case eType_Tag:
                return 4;
            case eType_OfsDelta:
                return 6;
            case eType_RefDelta:
                return 7;
        }
        return -1;
    }

    public static String GetObjTypeString(GitPackable.eType type) {
        switch (type) {
            case eType_Commit:
                return "commit";
            case eType_Tree:
                return "tree";
            case eType_Blob:
                return "blob";
        }
        return "";
    }

    private static int bitToWrite(long len)
    {
        int nbBits = 0;
        while (len > 0)
        {
            nbBits++;
            len = len >> 1;
        }
        int remains = (nbBits -4) % 7;
        if (remains > 0)
            nbBits += 7 -remains;
        return nbBits;
    }

    public static byte[] getObjHeader(GitPackable.eType type, long len) {
        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
        byte lastByte;
        lastByte = (byte) ((getObjType(type)) << 4);
        int nbBitToWrite = bitToWrite(len);
        nbBitToWrite -= 4;
        lastByte |= (byte) (len & 0b1111);
        len = len >> 4;
        while (nbBitToWrite > 0) {
            lastByte |= 0b10000000;
            buffer.write(lastByte);
            lastByte = 0;
            nbBitToWrite -= 7;
            lastByte |= (byte)(len & 0b1111111);
            len = len >> 7;
        }
        buffer.write(lastByte);
        return buffer.toByteArray();
    }

    public static byte[] deflate(byte[] in) throws IOException {
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        DeflaterOutputStream stream = new DeflaterOutputStream(output);
        stream.write(in);
        stream.finish();
        stream.flush();
        return output.toByteArray();
    }

    public static class Comparator implements java.util.Comparator<GitPackable> {
        @Override
        public int compare(GitPackable t1, GitPackable t2) {
            if (t1 instanceof GitObject && t2 instanceof GitObject)
                return ((GitObject) t2).GetDepth() - ((GitObject) t1).GetDepth();
            if (t1 instanceof GitObject /* then !(t2 instanceof GitObject) */)
                return -1;
            if (t2 instanceof GitObject /* then !(t1 instanceof GitObject) */)
                return 1;
            return (int)(((GitCommit)t1).GetTime().getTime() - ((GitCommit) t2).GetTime().getTime());
        }
    }
}
