/*
    Zlib – библиотека сжатия данных общего назначения. Версия 1.1.0
    Это изменённая объектно-ориентированная версия библиотеки, полностью
    совместимая с оригинальной библиотекой.
    
    Copyright © 1995–2005 Jean-loup Gailly и Mark Adler
    Copyright © 2000–2011 ymnk, JCraft, Inc.
    Copyright © 2016–2017, 2019–2022 Малик Разработчик
    
    Эта библиотека поставляется «как есть», без каких-либо явных или
    подразумеваемых гарантий. Ни при каких обстоятельствах авторы не
    несут какой-либо ответственности в случае потери данных вследствие
    использования данной библиотеки.
    
    Разрешается всем использовать эту библиотеку для любых целей, в том
    числе и для коммерческих приложений, а также изменять её и
    распространять свободно при соблюдении следующих условий:
    
        1. Оригинал библиотеки не должен быть искажён; вы не должны
    заявлять, что именно вы написали оригинальную библиотеку. Если вы
    используете эту библиотеку в своём программном продукте, то ссылка
    на авторов библиотеки была бы желательна, но это не является
    обязательным требованием.
    
        2. Изменённые версии исходных текстов должны быть отчётливо
    маркированы и не должны выдаваться за оригинал библиотеки.
    
        3. Эти замечания не могут быть удалены либо изменены при
    каком-либо варианте распространения исходных текстов.
*/

package malik.emulator.compression.zlib;

import java.io.*;

public class GZIPHeader extends Zlib
{
    private boolean fhcrc;
    private boolean text;
    private int mtime;
    int xflags;
    int os;
    int hcrc;
    int time;
    int crc;
    byte[] extra;
    byte[] name;
    byte[] comment;

    public GZIPHeader() {
        this.os = 255;
    }

    public void setOS(int osIndex) {
        if((osIndex < 0 || osIndex > 13) && osIndex != 255)
        {
            throw new IllegalArgumentException("os: " + osIndex);
        }
        this.os = osIndex;
    }

    public void setCRC(int crc) {
        this.crc = crc;
    }

    public void setModifiedTime(int mtime) {
        this.mtime = mtime;
    }

    public void setName(String name) {
        try
        {
            this.name = name.getBytes("ISO 8859-1");
        }
        catch(UnsupportedEncodingException e)
        {
            throw new IllegalArgumentException("name must be in ISO 8859-1 ".concat(name));
        }
    }

    public void setComment(String comment) {
        try
        {
            this.comment = comment.getBytes("ISO 8859-1");
        }
        catch(UnsupportedEncodingException e)
        {
            throw new IllegalArgumentException("comment must be in ISO 8859-1 ".concat(comment));
        }
    }

    public int getOS() {
        return os;
    }

    public int getCRC() {
        return crc;
    }

    public int getModifiedTime() {
        return mtime;
    }

    public String getName() {
        byte[] name = this.name;
        return name == null ? "" : new String(name);
    }

    public String getComment() {
        byte[] comment = this.comment;
        return comment == null ? "" : new String(comment);
    }

    public Object clone() {
        byte[] tmp;
        GZIPHeader gheader = new GZIPHeader();
        if(gheader.extra != null)
        {
            tmp = new byte[gheader.extra.length];
            Array.copy(gheader.extra, 0, tmp, 0, tmp.length);
            gheader.extra = tmp;
        }
        if(gheader.name != null)
        {
            tmp = new byte[gheader.name.length];
            Array.copy(gheader.name, 0, tmp, 0, tmp.length);
            gheader.name = tmp;
        }
        if(gheader.comment != null)
        {
            tmp = new byte[gheader.comment.length];
            Array.copy(gheader.comment, 0, tmp, 0, tmp.length);
            gheader.comment = tmp;
        }
        return gheader;
    }

    final void put(Deflate d) {
        int flag = 0;
        int xfl = 0;
        if(text) flag |= 1;
        if(fhcrc) flag |= 2;
        if(extra != null) flag |= 4;
        if(name != null) flag |= 8;
        if(comment != null) flag |= 16;
        switch(d.level)
        {
        case BEST_SPEED:
            xfl |= 4;
            break;
        case BEST_COMPRESSION:
            xfl |= 2;
            break;
        }
        d.putShort((short) 0x8b1f);
        d.putByte((byte) 8);
        d.putByte((byte) flag);
        d.putByte((byte) mtime);
        d.putByte((byte) (mtime >> 8));
        d.putByte((byte) (mtime >> 16));
        d.putByte((byte) (mtime >> 24));
        d.putByte((byte) xfl);
        d.putByte((byte) os);
        if(extra != null)
        {
            d.putByte((byte) extra.length);
            d.putByte((byte) (extra.length >> 8));
            d.putBytes(extra, 0, extra.length);
        }
        if(name != null)
        {
            d.putBytes(name, 0, name.length);
            d.putByte((byte) 0);
        }
        if(comment != null)
        {
            d.putBytes(comment, 0, comment.length);
            d.putByte((byte) 0);
        }
    }
}
