/*-
 * Copyright (C) 2011-2012 Erik Larsson
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.catacombae.hfs.types.hfsplus;

import java.io.PrintStream;
import java.math.BigInteger;
import org.catacombae.csjc.PrintableStruct;
import org.catacombae.csjc.StaticStruct;
import org.catacombae.util.Util;

/**
 * This class was generated by CStructToJavaClass.
 *
 * @author <a href="https://catacombae.org" target="_top">Erik Larsson</a>
 */
public class BlockInfo implements StaticStruct, PrintableStruct {
    /*
     * struct BlockInfo
     * size: 16 bytes
     * description:
     *
     * BP  Size  Type    Identifier  Description
     * -----------------------------------------
     * 0   8     UInt64  bnum
     * 8   4     UInt32  bsize
     * 12  4     UInt32  next
     */

    public static final int STRUCTSIZE = 16;

    private final boolean littleEndian;

    private long bnum;
    private int bsize;
    private int next;

    public BlockInfo(byte[] data, int offset, boolean littleEndian) {
        this.littleEndian = littleEndian;

        if(!littleEndian) {
            this.bnum = Util.readLongBE(data, offset+0);
            this.bsize = Util.readIntBE(data, offset+8);
            this.next = Util.readIntBE(data, offset+12);
        }
        else {
            this.bnum = Util.readLongLE(data, offset+0);
            this.bsize = Util.readIntLE(data, offset+8);
            this.next = Util.readIntLE(data, offset+12);
        }
    }

    public static int length() { return STRUCTSIZE; }

    public int size() { return length(); }

    public final boolean isLittleEndian() { return littleEndian; }

    /**  */
    public final BigInteger getBnum() { return Util.unsign(getRawBnum()); }
    /**  */
    public final long getBsize() { return Util.unsign(getRawBsize()); }
    /**  */
    public final long getNext() { return Util.unsign(getRawNext()); }

    /** <b>Note that the return value from this function should be interpreted as an unsigned integer, for instance using Util.unsign(...).</b> */
    public final long getRawBnum() { return bnum; }
    /** <b>Note that the return value from this function should be interpreted as an unsigned integer, for instance using Util.unsign(...).</b> */
    public final int getRawBsize() { return bsize; }
    /** <b>Note that the return value from this function should be interpreted as an unsigned integer, for instance using Util.unsign(...).</b> */
    public final int getRawNext() { return next; }

    public void printFields(PrintStream ps, String prefix) {
        ps.println(prefix + " bnum: " + getBnum());
        ps.println(prefix + " bsize: " + getBsize());
        ps.println(prefix + " next: " + getNext());
    }

    public void print(PrintStream ps, String prefix) {
        ps.println(prefix + "BlockInfo:");
        printFields(ps, prefix);
    }

    public byte[] getBytes() {
        byte[] result = new byte[length()];
        getBytes(result, 0);
        return result;
    }

    public int getBytes(byte[] result, int offset) {
        final int originalOffset = offset;

        if(!littleEndian) {
            Util.arrayPutBE(result, offset, bnum); offset += 8;
            Util.arrayPutBE(result, offset, bsize); offset += 4;
            Util.arrayPutBE(result, offset, next); offset += 4;
        }
        else {
            Util.arrayPutLE(result, offset, bnum); offset += 8;
            Util.arrayPutLE(result, offset, bsize); offset += 4;
            Util.arrayPutLE(result, offset, next); offset += 4;
        }

        return offset - originalOffset;
    }
}
