/* ====================================================================
   Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed with
   this work for additional information regarding copyright ownership.
   The ASF licenses this file to You under the Apache License, Version 2.0
   (the "License"); you may not use this file except in compliance with
   the License.  You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
==================================================================== */

package org.apache.poi.hpsf;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.apache.poi.EmptyFileException;
import org.apache.poi.hpsf.wellknown.PropertyIDMap;
import org.apache.poi.poifs.filesystem.DirectoryEntry;
import org.apache.poi.poifs.filesystem.Entry;
import org.apache.poi.util.CodePageUtil;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.LittleEndianByteArrayInputStream;
import org.apache.poi.util.LittleEndianConsts;
import org.apache.poi.util.LittleEndianOutputStream;
import org.apache.poi.util.NotImplemented;
import org.apache.poi.util.Removal;

/**
 * Represents a property set in the Horrible Property Set Format
 * (HPSF). These are usually metadata of a Microsoft Office
 * document.<p>
 *
 * An application that wants to access these metadata should create
 * an instance of this class or one of its subclasses by calling the
 * factory method {@link PropertySetFactory#create} and then retrieve
 * the information its needs by calling appropriate methods.<p>
 *
 * {@link PropertySetFactory#create} does its work by calling one
 * of the constructors {@link PropertySet#PropertySet(InputStream)} or
 * {@link PropertySet#PropertySet(byte[])}. If the constructor's
 * argument is not in the Horrible Property Set Format, i.e. not a
 * property set stream, or if any other error occurs, an appropriate
 * exception is thrown.<p>
 *
 * A {@link PropertySet} has a list of {@link Section}s, and each
 * {@link Section} has a {@link Property} array. Use {@link
 * #getSections} to retrieve the {@link Section}s, then call {@link
 * Section#getProperties} for each {@link Section} to get hold of the
 * {@link Property} arrays.<p>
 *
 * Since the vast majority of {@link PropertySet}s contains only a single
 * {@link Section}, the convenience method {@link #getProperties} returns
 * the properties of a {@link PropertySet}'s {@link Section} (throwing a
 * {@link NoSingleSectionException} if the {@link PropertySet} contains
 * more (or less) than exactly one {@link Section}).
 */
public class PropertySet {
    /**
     * If the OS version field holds this value the property set stream was
     * created on a 16-bit Windows system.
     */
    public static final int OS_WIN16     = 0x0000;

    /**
     * If the OS version field holds this value the property set stream was
     * created on a Macintosh system.
     */
    public static final int OS_MACINTOSH = 0x0001;

    /**
     * If the OS version field holds this value the property set stream was
     * created on a 32-bit Windows system.
     */
    public static final int OS_WIN32     = 0x0002;

    /**
     * The "byteOrder" field must equal this value.
     */
    /* package */ static final int BYTE_ORDER_ASSERTION = 0xFFFE;

    /**
     * The "format" field must equal this value.
     */
    /* package */ static final int FORMAT_ASSERTION = 0x0000;

    /**
     * The length of the property set stream header.
     */
    /* package */ static final int OFFSET_HEADER =
        LittleEndianConsts.SHORT_SIZE + /* Byte order    */
        LittleEndianConsts.SHORT_SIZE + /* Format        */
        LittleEndianConsts.INT_SIZE +   /* OS version    */
        ClassID.LENGTH +                /* Class ID      */
        LittleEndianConsts.INT_SIZE;    /* Section count */


    /**
     * Specifies this {@link PropertySet}'s byte order. See the
     * HPFS documentation for details!
     */
    private int byteOrder;

    /**
     * Specifies this {@link PropertySet}'s format. See the HPFS
     * documentation for details!
     */
    private int format;

    /**
     * Specifies the version of the operating system that created this
     * {@link PropertySet}. See the HPFS documentation for details!
     */
    private int osVersion;

    /**
     * Specifies this {@link PropertySet}'s "classID" field. See
     * the HPFS documentation for details!
     */
    private ClassID classID;

    /**
     * The sections in this {@link PropertySet}.
     */
    private final List<Section> sections = new ArrayList<>();


    /**
     * Constructs a {@code PropertySet} instance. Its
     * primary task is to initialize the field with their proper values.
     * It also sets fields that might change to reasonable defaults.
     */
    public PropertySet() {
        /* Initialize the "byteOrder" field. */
        byteOrder = BYTE_ORDER_ASSERTION;

        /* Initialize the "format" field. */
        format = FORMAT_ASSERTION;

        /* Initialize "osVersion" field as if the property has been created on
         * a Win32 platform, whether this is the case or not. */
        osVersion = (OS_WIN32 << 16) | 0x0A04;

        /* Initialize the "classID" field. */
        classID = new ClassID();

        /* Initialize the sections. Since property set must have at least
         * one section it is added right here. */
        addSection(new Section());
    }



    /**
     * Creates a {@link PropertySet} instance from an {@link
     * InputStream} in the Horrible Property Set Format.<p>
     *
     * The constructor reads the first few bytes from the stream
     * and determines whether it is really a property set stream. If
     * it is, it parses the rest of the stream. If it is not, it
     * resets the stream to its beginning in order to let other
     * components mess around with the data and throws an
     * exception.
     *
     * @param stream Holds the data making out the property set
     * stream.
     * @throws IOException
     *    if the {@link InputStream} cannot be accessed as needed.
     * @exception NoPropertySetStreamException
     *    if the input stream does not contain a property set.
     * @exception UnsupportedEncodingException
     *    if a character encoding is not supported.
     */
    public PropertySet(final InputStream stream)
    throws NoPropertySetStreamException, IOException {
        if (!isPropertySetStream(stream)) {
            throw new NoPropertySetStreamException();
        }

        final byte[] buffer = IOUtils.toByteArray(stream);
        init(buffer, 0, buffer.length);
    }



    /**
     * Creates a {@link PropertySet} instance from a byte array that
     * represents a stream in the Horrible Property Set Format.
     *
     * @param stream The byte array holding the stream data.
     * @param offset The offset in {@code stream} where the stream
     * data begin. If the stream data begin with the first byte in the
     * array, the {@code offset} is 0.
     * @param length The length of the stream data.
     * @throws NoPropertySetStreamException if the byte array is not a
     * property set stream.
     *
     * @exception UnsupportedEncodingException if the codepage is not supported.
     */
    public PropertySet(final byte[] stream, final int offset, final int length)
    throws NoPropertySetStreamException, UnsupportedEncodingException {
        if (!isPropertySetStream(stream, offset, length)) {
            throw new NoPropertySetStreamException();
        }
        init(stream, offset, length);
    }

    /**
     * Creates a {@link PropertySet} instance from a byte array
     * that represents a stream in the Horrible Property Set Format.
     *
     * @param stream The byte array holding the stream data. The
     * complete byte array contents is the stream data.
     * @throws NoPropertySetStreamException if the byte array is not a
     * property set stream.
     *
     * @exception UnsupportedEncodingException if the codepage is not supported.
     */
    public PropertySet(final byte[] stream)
    throws NoPropertySetStreamException, UnsupportedEncodingException {
        this(stream, 0, stream.length);
    }

    /**
     * Constructs a {@code PropertySet} by doing a deep copy of
     * an existing {@code PropertySet}. All nested elements, i.e.
     * {@code Section}s and {@code Property} instances, will be their
     * counterparts in the new {@code PropertySet}.
     *
     * @param ps The property set to copy
     */
    public PropertySet(PropertySet ps) {
        setByteOrder(ps.getByteOrder());
        setFormat(ps.getFormat());
        setOSVersion(ps.getOSVersion());
        setClassID(ps.getClassID());
        for (final Section section : ps.getSections()) {
            sections.add(new Section(section));
        }
    }


    /**
     * @return The property set stream's low-level "byte order" field. It is always {@code 0xFFFE}.
     */
    public int getByteOrder() {
        return byteOrder;
    }

    /**
     * Returns the property set stream's low-level "byte order" field.
     *
     * @param byteOrder The property set stream's low-level "byte order" field.
     */
    @SuppressWarnings("WeakerAccess")
    public void setByteOrder(int byteOrder) {
        this.byteOrder = byteOrder;
    }

    /**
     * @return The property set stream's low-level "format" field. It is always {@code 0x0000}.
     */
    public int getFormat() {
        return format;
    }

    /**
     * Sets the property set stream's low-level "format" field.
     *
     * @param format The property set stream's low-level "format" field.
     */
    public void setFormat(int format) {
        this.format = format;
    }

    /**
     * @return The property set stream's low-level "OS version" field.
     */
    public int getOSVersion() {
        return osVersion;
    }

    /**
     * Sets the property set stream's low-level "OS version" field.
     *
     * @param osVersion The property set stream's low-level "OS version" field.
     */
    @SuppressWarnings("WeakerAccess")
    public void setOSVersion(int osVersion) {
        this.osVersion = osVersion;
    }


    /**
     * @return The property set stream's low-level "class ID" field.
     */
    public ClassID getClassID() {
        return classID;
    }

    /**
     * Sets the property set stream's low-level "class ID" field.
     *
     * @param classID The property set stream's low-level "class ID" field.
     */
    @SuppressWarnings("WeakerAccess")
    public void setClassID(ClassID classID) {
        this.classID = classID;
    }

    /**
     * @return The number of {@link Section}s in the property set.
     */
    public int getSectionCount() {
        return sections.size();
    }

    /**
     * @return The unmodifiable list of {@link Section}s in the property set.
     */
    public List<Section> getSections() {
        return Collections.unmodifiableList(sections);
    }



    /**
     * Adds a section to this property set.
     *
     * @param section The {@link Section} to add. It will be appended
     * after any sections that are already present in the property set
     * and thus become the last section.
     */
    public void addSection(final Section section) {
        sections.add(section);
    }

    /**
     * Removes all sections from this property set.
     */
    public void clearSections() {
        sections.clear();
    }

    /**
     * The id to name mapping of the properties in this set.
     *
     * @return the id to name mapping of the properties in this set or {@code null} if not applicable
     */
    public PropertyIDMap getPropertySetIDMap() {
        return null;
    }


    /**
     * Checks whether an {@link InputStream} is in the Horrible
     * Property Set Format.
     *
     * @param stream The {@link InputStream} to check. In order to
     * perform the check, the method reads the first bytes from the
     * stream. After reading, the stream is reset to the position it
     * had before reading. The {@link InputStream} must support the
     * {@link InputStream#mark} method.
     * @return {@code true} if the stream is a property set
     * stream, else {@code false}.
     * @exception IOException if an I/O error occurs
     */
    public static boolean isPropertySetStream(final InputStream stream) throws IOException {
        /*
         * Read at most this many bytes.
         */
        final int BUFFER_SIZE = 50;

        /*
         * Read a couple of bytes from the stream.
         */
        try {
            final byte[] buffer = IOUtils.peekFirstNBytes(stream, BUFFER_SIZE);
            return isPropertySetStream(buffer, 0, buffer.length);
        } catch (EmptyFileException e) {
            return false;
        }
    }



    /**
     * Checks whether a byte array is in the Horrible Property Set Format.
     *
     * @param src The byte array to check.
     * @param offset The offset in the byte array.
     * @param length The significant number of bytes in the byte
     * array. Only this number of bytes will be checked.
     * @return {@code true} if the byte array is a property set
     * stream, {@code false} if not.
     */
    @SuppressWarnings({"unused", "WeakerAccess"})
    public static boolean isPropertySetStream(final byte[] src, final int offset, final int length) {
        LittleEndianByteArrayInputStream leis = new LittleEndianByteArrayInputStream(src, offset, length);

        /*
         * Read the header fields of the stream. They must always be
         * there.
         */
        try {
            final int byteOrder = leis.readUShort();
            if (byteOrder != BYTE_ORDER_ASSERTION) {
                return false;
            }
            final int format = leis.readUShort();
            if (format != FORMAT_ASSERTION) {
                return false;
            }
            final long osVersion = leis.readUInt();
            if (leis.skip(ClassID.LENGTH) != ClassID.LENGTH) {
                return false;
            }
            final long sectionCount = leis.readUInt();
            return (sectionCount >= 0);
        } catch (RuntimeException e) {
            return false;
        }
    }



    /**
     * Initializes this {@link PropertySet} instance from a byte
     * array. The method assumes that it has been checked already that
     * the byte array indeed represents a property set stream. It does
     * no more checks on its own.
     *
     * @param src Byte array containing the property set stream
     * @param offset The property set stream starts at this offset
     * from the beginning of {@code src}
     * @param length Length of the property set stream.
     * @throws UnsupportedEncodingException if HPSF does not (yet) support the
     * property set's character encoding.
     */
    private void init(final byte[] src, final int offset, final int length)
    throws UnsupportedEncodingException {
        /* FIXME (3): Ensure that at most "length" bytes are read. */

        /*
         * Read the stream's header fields.
         */
        int o = offset;
        byteOrder = LittleEndian.getUShort(src, o);
        o += LittleEndianConsts.SHORT_SIZE;
        format = LittleEndian.getUShort(src, o);
        o += LittleEndianConsts.SHORT_SIZE;
        osVersion = (int) LittleEndian.getUInt(src, o);
        o += LittleEndianConsts.INT_SIZE;
        classID = new ClassID(src, o);
        o += ClassID.LENGTH;
        final int sectionCount = LittleEndian.getInt(src, o);
        o += LittleEndianConsts.INT_SIZE;
        if (sectionCount < 0) {
            throw new HPSFRuntimeException("Section count " + sectionCount + " is negative.");
        }

        /*
         * Read the sections, which are following the header. They
         * start with an array of section descriptions. Each one
         * consists of a format ID telling what the section contains
         * and an offset telling how many bytes from the start of the
         * stream the section begins.
         *
         * Most property sets have only one section. The Document
         * Summary Information stream has 2. Everything else is a rare
         * exception and is no longer fostered by Microsoft.
         */

        /*
         * Loop over the section descriptor array. Each descriptor
         * consists of a ClassID and a DWord, and we have to increment
         * "offset" accordingly.
         */
        for (int i = 0; i < sectionCount; i++) {
            final Section s = new Section(src, o);
            o += ClassID.LENGTH + LittleEndianConsts.INT_SIZE;
            sections.add(s);
        }
    }

    /**
     * Writes the property set to an output stream.
     *
     * @param out the output stream to write the section to
     * @exception IOException if an error when writing to the output stream
     * occurs
     * @exception WritingNotSupportedException if HPSF does not yet support
     * writing a property's variant type.
     */
    public void write(final OutputStream out) throws IOException, WritingNotSupportedException {

        out.write(toBytes());

        /* Indicate that we're done */
        out.close();
    }

    private byte[] toBytes() throws WritingNotSupportedException, IOException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        LittleEndianOutputStream leos = new LittleEndianOutputStream(bos);

        /* Write the number of sections in this property set stream. */
        final int nrSections = getSectionCount();

        /* Write the property set's header. */
        leos.writeShort(getByteOrder());
        leos.writeShort(getFormat());
        leos.writeInt(getOSVersion());
        putClassId(bos, getClassID());
        leos.writeInt(nrSections);

        assert(bos.size() == OFFSET_HEADER);

        final int[][] offsets = new int[getSectionCount()][2];

        /* Write the section list, i.e. the references to the sections. Each
         * entry in the section list consist of the section's class ID and the
         * section's offset relative to the beginning of the stream. */
        int secCnt = 0;
        for (final Section section : getSections()) {
            final ClassID formatID = section.getFormatID();
            if (formatID == null) {
                throw new NoFormatIDException();
            }
            putClassId(bos, formatID);
            offsets[secCnt++][0] = bos.size();
            // offset dummy - filled later
            leos.writeInt(-1);
        }

        /* Write the sections themselves. */
        secCnt = 0;
        for (final Section section : getSections()) {
            offsets[secCnt++][1] = bos.size();
            section.write(bos);
        }

        byte[] result = bos.toByteArray();
        for (int[] off : offsets) {
            LittleEndian.putInt(result, off[0], off[1]);
        }

        return result;
    }

    /**
     * Writes a property set to a document in a POI filesystem directory.
     *
     * @param dir The directory in the POI filesystem to write the document to.
     * @param name The document's name. If there is already a document with the
     * same name in the directory the latter will be overwritten.
     *
     * @throws WritingNotSupportedException if the filesystem doesn't support writing
     * @throws IOException if the old entry can't be deleted or the new entry be written
     */
    public void write(final DirectoryEntry dir, final String name)
    throws WritingNotSupportedException, IOException {
        /* If there is already an entry with the same name, remove it. */
        if (dir.hasEntry(name)) {
            final Entry e = dir.getEntry(name);
            e.delete();
        }

        /* Create the new entry. */
        dir.createDocument(name, toInputStream());
    }

    /**
     * Returns the contents of this property set stream as an input stream.
     * The latter can be used for example to write the property set into a POIFS
     * document. The input stream represents a snapshot of the property set.
     * If the latter is modified while the input stream is still being
     * read, the modifications will not be reflected in the input stream but in
     * the {@link PropertySet} only.
     *
     * @return the contents of this property set stream
     *
     * @throws WritingNotSupportedException if HPSF does not yet support writing
     * of a property's variant type.
     * @throws IOException if an I/O exception occurs.
     */
    public InputStream toInputStream() throws WritingNotSupportedException, IOException {
        return new ByteArrayInputStream(toBytes());
    }

    /**
     * Fetches the property with the given ID, then does its
     *  best to return it as a String
     *
     * @param propertyId the property id
     *
     * @return The property as a String, or null if unavailable
     */
    String getPropertyStringValue(final int propertyId) {
        Object propertyValue = getProperty(propertyId);
        return getPropertyStringValue(propertyValue);
    }

    /**
     * Return the string representation of a property value
     *
     * @param propertyValue the property value
     *
     * @return The property value as a String, or null if unavailable
     */
    public static String getPropertyStringValue(final Object propertyValue) {
        // Normal cases
        if (propertyValue == null) {
            return null;
        }
        if (propertyValue instanceof String) {
            return (String)propertyValue;
        }

        // Do our best with some edge cases
        if (propertyValue instanceof byte[]) {
            byte[] b = (byte[])propertyValue;
            switch (b.length) {
                case 0:
                    return "";
                case 1:
                    return Byte.toString(b[0]);
                case 2:
                    return Integer.toString( LittleEndian.getUShort(b) );
                case 4:
                    return Long.toString( LittleEndian.getUInt(b) );
                default:
                    // Maybe it's a string? who knows!
                    try {
                        return CodePageUtil.getStringFromCodePage(b, Property.DEFAULT_CODEPAGE);
                    } catch (UnsupportedEncodingException e) {
                        // doesn't happen ...
                        return "";
                    }
            }
        }
        return propertyValue.toString();
    }

    /**
     * Checks whether this {@link PropertySet} represents a Summary Information.
     *
     * @return {@code true} if this {@link PropertySet}
     * represents a Summary Information, else {@code false}.
     */
    public boolean isSummaryInformation() {
        return !sections.isEmpty() && matchesSummary(getFirstSection().getFormatID(), SummaryInformation.FORMAT_ID);
    }

    /**
     * Checks whether this {@link PropertySet} is a Document Summary Information.
     *
     * @return {@code true} if this {@link PropertySet}
     * represents a Document Summary Information, else {@code false}.
     */
    public boolean isDocumentSummaryInformation() {
        return !sections.isEmpty() && matchesSummary(getFirstSection().getFormatID(), DocumentSummaryInformation.FORMAT_ID);
    }

    /* package */ static boolean matchesSummary(ClassID actual, ClassID... expected) {
        for (ClassID sum : expected) {
            if (sum.equals(actual) || sum.equalsInverted(actual)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Convenience method returning the {@link Property} array contained in this
     * property set. It is a shortcut for getting he {@link PropertySet}'s
     * {@link Section}s list and then getting the {@link Property} array from the
     * first {@link Section}.
     *
     * @return The properties of the only {@link Section} of this
     * {@link PropertySet}.
     * @throws NoSingleSectionException if the {@link PropertySet} has
     * more or less than one {@link Section}.
     */
    public Property[] getProperties() throws NoSingleSectionException {
        return getFirstSection().getProperties();
    }



    /**
     * Convenience method returning the value of the property with the specified ID.
     * If the property is not available, {@code null} is returned and a subsequent
     * call to {@link #wasNull} will return {@code true}.
     *
     * @param id The property ID
     * @return The property value
     * @throws NoSingleSectionException if the {@link PropertySet} has
     * more or less than one {@link Section}.
     */
    protected Object getProperty(final int id) throws NoSingleSectionException {
        return getFirstSection().getProperty(id);
    }



    /**
     * Convenience method returning the value of a boolean property with the
     * specified ID. If the property is not available, {@code false} is returned.
     * A subsequent call to {@link #wasNull} will return {@code true} to let the
     * caller distinguish that case from a real property value of {@code false}.
     *
     * @param id The property ID
     * @return The property value
     * @throws NoSingleSectionException if the {@link PropertySet} has
     * more or less than one {@link Section}.
     */
    boolean getPropertyBooleanValue(final int id) throws NoSingleSectionException {
        return getFirstSection().getPropertyBooleanValue(id);
    }



    /**
     * Convenience method returning the value of the numeric
     * property with the specified ID. If the property is not
     * available, 0 is returned. A subsequent call to {@link #wasNull}
     * will return {@code true} to let the caller distinguish
     * that case from a real property value of 0.
     *
     * @param id The property ID
     * @return The propertyIntValue value
     * @throws NoSingleSectionException if the {@link PropertySet} has
     * more or less than one {@link Section}.
     */
    int getPropertyIntValue(final int id) throws NoSingleSectionException {
        return getFirstSection().getPropertyIntValue(id);
    }



    /**
     * Checks whether the property which the last call to {@link
     * #getPropertyIntValue} or {@link #getProperty} tried to access
     * was available or not. This information might be important for
     * callers of {@link #getPropertyIntValue} since the latter
     * returns 0 if the property does not exist. Using wasNull,
     * the caller can distinguish this case from a
     * property's real value of 0.
     *
     * @return {@code true} if the last call to {@link
     * #getPropertyIntValue} or {@link #getProperty} tried to access a
     * property that was not available, else {@code false}.
     * @throws NoSingleSectionException if the {@link PropertySet} has
     * more than one {@link Section}.
     */
    public boolean wasNull() throws NoSingleSectionException {
        return getFirstSection().wasNull();
    }



    /**
     * Gets the {@link PropertySet}'s first section.
     *
     * @return The {@link PropertySet}'s first section.
     */
    @SuppressWarnings("WeakerAccess")
    public Section getFirstSection() {
        if (sections.isEmpty()) {
            throw new MissingSectionException("Property set does not contain any sections.");
        }
        return sections.get(0);
    }


    /**
     * Returns {@code true} if the {@code PropertySet} is equal
     * to the specified parameter, else {@code false}.
     *
     * @param o the object to compare this {@code PropertySet} with
     *
     * @return {@code true} if the objects are equal, {@code false}
     * if not
     */
    @Override
    public boolean equals(final Object o) {
        if (!(o instanceof PropertySet)) {
            return false;
        }
        final PropertySet ps = (PropertySet) o;
        int byteOrder1 = ps.getByteOrder();
        int byteOrder2 = getByteOrder();
        ClassID classID1 = ps.getClassID();
        ClassID classID2 = getClassID();
        int format1 = ps.getFormat();
        int format2 = getFormat();
        int osVersion1 = ps.getOSVersion();
        int osVersion2 = getOSVersion();
        int sectionCount1 = ps.getSectionCount();
        int sectionCount2 = getSectionCount();
        if (byteOrder1 != byteOrder2      ||
            !classID1.equals(classID2)    ||
            format1 != format2            ||
            osVersion1 != osVersion2      ||
            sectionCount1 != sectionCount2) {
            return false;
        }

        /* Compare the sections: */
        return getSections().containsAll(ps.getSections());
    }



    /**
     * @see Object#hashCode()
     */
    @NotImplemented
    @Override
    public int hashCode() {
        throw new UnsupportedOperationException("FIXME: Not yet implemented.");
    }



    /**
     * @see Object#toString()
     */
    @Override
    public String toString() {
        final StringBuilder b = new StringBuilder();
        final int sectionCount = getSectionCount();
        b.append(getClass().getName());
        b.append('[');
        b.append("byteOrder: ");
        b.append(getByteOrder());
        b.append(", classID: ");
        b.append(getClassID());
        b.append(", format: ");
        b.append(getFormat());
        b.append(", OSVersion: ");
        b.append(getOSVersion());
        b.append(", sectionCount: ");
        b.append(sectionCount);
        b.append(", sections: [\n");
        for (Section section: getSections()) {
            b.append(section.toString(getPropertySetIDMap()));
        }
        b.append(']');
        b.append(']');
        return b.toString();
    }


    void remove1stProperty(long id) {
        getFirstSection().removeProperty(id);
    }

    void set1stProperty(long id, String value) {
        getFirstSection().setProperty((int)id, value);
    }

    void set1stProperty(long id, int value) {
        getFirstSection().setProperty((int)id, value);
    }

    void set1stProperty(long id, boolean value) {
        getFirstSection().setProperty((int)id, value);
    }

    @SuppressWarnings("SameParameterValue")
    void set1stProperty(long id, byte[] value) {
        getFirstSection().setProperty((int)id, value);
    }

    private static void putClassId(final ByteArrayOutputStream out, final ClassID n) {
        byte[] b = new byte[16];
        n.write(b, 0);
        out.write(b, 0, b.length);
    }
}
