/*-
 * Copyright (C) 2021 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.hfsexplorer.types.dsstore;

import java.io.PrintStream;
import org.catacombae.csjc.DynamicStruct;
import org.catacombae.util.Util;

/** This class was generated by CStructToJavaClass. */
public class DSStoreRootBlock implements DynamicStruct {
    /*
     * struct DSStoreRootBlock
     * size: 16 bytes
     * description:
     *
     * BP  Size   Type     Identifier  Description
     * ----------------------------------------------------------
     * 0   4      be32     unknown
     * 4   4      be32     numOffsets
     * 8   4      be32     unknown2    Zeroed in all known cases.
     * 12  4 * 1  be32[1]  offsetList
     */

    public static final int STATIC_STRUCTSIZE = 12;

    private int unknown;
    private int numOffsets;
    private int unknown2;
    private int offsetList[];

    public DSStoreRootBlock(byte[] data, int offset) {
        this.unknown = Util.readIntBE(data, offset + 0);
        this.numOffsets = Util.readIntBE(data, offset + 4);
        this.unknown2 = Util.readIntBE(data, offset + 8);
        this.offsetList = new int[this.numOffsets];
        for(int i = 0; i < this.numOffsets; ++i) {
            this.offsetList[i] = Util.readIntBE(data, offset + 12 + i * 4);
        }
    }

    public int maxSize() {
        /*
         * The struct is padded up to 1024 + 12 bytes.
         * See: https://0day.work/parsing-the-ds_store-file-format/
         */
        return 0x40c;
    }

    public int occupiedSize() {
        return STATIC_STRUCTSIZE + this.numOffsets * 4;
    }

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

    /**  */
    public final long getUnknown() {
        return Util.unsign(getRawUnknown());
    }

    /**  */
    public final long getNumOffsets() {
        return Util.unsign(getRawNumOffsets());
    }

    /** Zeroed in all known cases. */
    public final long getUnknown2() {
        return Util.unsign(getRawUnknown2());
    }

    /**  */
    public final long[] getOffsetList() {
        return Util.unsign(getRawOffsetList());
    }

    /**
     * <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 getRawUnknown() {
        return this.unknown;
    }

    /**
     * <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 getRawNumOffsets() {
        return this.numOffsets;
    }

    /**
     * <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 getRawUnknown2() {
        return this.unknown2;
    }

    /**
     * <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[] getRawOffsetList() {
        return Util.arrayCopy(this.offsetList, new int[this.offsetList.length]);
    }

    public void printFields(PrintStream ps, String prefix) {
        ps.println(prefix + " unknown: " + getUnknown());
        ps.println(prefix + " numOffsets: " + getNumOffsets());
        ps.println(prefix + " unknown2: " + getUnknown2());
        ps.println(prefix + " offsetList: ");
        {
            long[] _array = getOffsetList();
            for(int _i = 0; _i < this.offsetList.length; ++_i) {
                ps.println(prefix + "   " + _array[_i] + " " +
                        "(0x" + Util.toHexStringBE(_array[_i]) + ")");
            }
        }
    }

    public void print(PrintStream ps, String prefix) {
        ps.println(prefix + "DSStoreRootBlock:");
        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 startOffset = offset;

        Util.arrayPutBE(result, offset, this.unknown); offset += 4;
        Util.arrayPutBE(result, offset, this.numOffsets); offset += 4;
        Util.arrayPutBE(result, offset, this.unknown2); offset += 4;
        Util.arrayPutBE(result, offset, this.offsetList); offset += 4;

        return offset - startOffset;
    }
}
