/* ====================================================================
   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.poifs.filesystem;

import java.io.ByteArrayOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.ReadableByteChannel;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.math3.util.ArithmeticUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.poi.EmptyFileException;
import org.apache.poi.poifs.common.POIFSBigBlockSize;
import org.apache.poi.poifs.common.POIFSConstants;
import org.apache.poi.poifs.dev.POIFSViewable;
import org.apache.poi.poifs.nio.ByteArrayBackedDataSource;
import org.apache.poi.poifs.nio.DataSource;
import org.apache.poi.poifs.nio.FileBackedDataSource;
import org.apache.poi.poifs.property.DirectoryProperty;
import org.apache.poi.poifs.property.DocumentProperty;
import org.apache.poi.poifs.property.PropertyTable;
import org.apache.poi.poifs.storage.BATBlock;
import org.apache.poi.poifs.storage.BATBlock.BATBlockAndIndex;
import org.apache.poi.poifs.storage.HeaderBlock;
import org.apache.poi.util.IOUtils;
import org.apache.poi.util.Internal;

/**
 * <p>This is the main class of the POIFS system; it manages the entire
 * life cycle of the filesystem.</p>
 * <p>This is the new NIO version, which uses less memory</p>
 */

public class POIFSFileSystem extends BlockStore
        implements POIFSViewable, Closeable {
    //arbitrarily selected; may need to increase
    private static final int MAX_RECORD_LENGTH = 100_000;

    private static final Logger LOG = LogManager.getLogger(POIFSFileSystem.class);

    /**
     * Maximum number size (in blocks) of the allocation table as supported by
     * POI.<p>
     * <p>
     * This constant has been chosen to help POI identify corrupted data in the
     * header block (rather than crash immediately with {@link OutOfMemoryError}
     * ). It's not clear if the compound document format actually specifies any
     * upper limits. For files with 512 byte blocks, having an allocation table
     * of 65,335 blocks would correspond to a total file size of 4GB. Needless
     * to say, POI probably cannot handle files anywhere near that size.
     */
    private static final int MAX_BLOCK_COUNT = 65535;

    private POIFSMiniStore _mini_store;
    private PropertyTable _property_table;
    private final List<BATBlock> _xbat_blocks;
    private final List<BATBlock> _bat_blocks;
    private HeaderBlock _header;
    private DirectoryNode _root;

    protected DataSource _data;

    /**
     * What big block size the file uses. Most files
     * use 512 bytes, but a few use 4096
     */
    private POIFSBigBlockSize bigBlockSize =
            POIFSConstants.SMALLER_BIG_BLOCK_SIZE_DETAILS;

    private POIFSFileSystem(boolean newFS) {
        _header = new HeaderBlock(bigBlockSize);
        _property_table = new PropertyTable(_header);
        _mini_store = new POIFSMiniStore(this, _property_table.getRoot(), new ArrayList<>(), _header);
        _xbat_blocks = new ArrayList<>();
        _bat_blocks = new ArrayList<>();
        _root = null;

        if (newFS) {
            createNewDataSource();
        }
    }

    protected void createNewDataSource() {
        // Data needs to initially hold just the header block,
        //  a single bat block, and an empty properties section
        long blockSize = ArithmeticUtils.mulAndCheck(bigBlockSize.getBigBlockSize(), 3L);
        _data = new ByteArrayBackedDataSource(IOUtils.safelyAllocate(blockSize, MAX_RECORD_LENGTH));
    }

    /**
     * Constructor, intended for writing
     */
    public POIFSFileSystem() {
        this(true);

        // Reserve block 0 for the start of the Properties Table
        // Create a single empty BAT, at pop that at offset 1
        _header.setBATCount(1);
        _header.setBATArray(new int[]{1});
        BATBlock bb = BATBlock.createEmptyBATBlock(bigBlockSize, false);
        bb.setOurBlockIndex(1);
        _bat_blocks.add(bb);

        setNextBlock(0, POIFSConstants.END_OF_CHAIN);
        setNextBlock(1, POIFSConstants.FAT_SECTOR_BLOCK);

        _property_table.setStartBlock(0);
    }

    /**
     * <p>Creates a POIFSFileSystem from a <tt>File</tt>. This uses less memory than
     * creating from an <tt>InputStream</tt>. The File will be opened read-only</p>
     *
     * <p>Note that with this constructor, you will need to call {@link #close()}
     * when you're done to have the underlying file closed, as the file is
     * kept open during normal operation to read the data out.</p>
     *
     * @param file the File from which to read the data
     * @throws IOException on errors reading, or on invalid data
     */
    public POIFSFileSystem(File file)
            throws IOException {
        this(file, true);
    }

    /**
     * <p>Creates a POIFSFileSystem from a <tt>File</tt>. This uses less memory than
     * creating from an <tt>InputStream</tt>.</p>
     *
     * <p>Note that with this constructor, you will need to call {@link #close()}
     * when you're done to have the underlying file closed, as the file is
     * kept open during normal operation to read the data out.</p>
     *
     * @param file     the File from which to read or read/write the data
     * @param readOnly whether the POIFileSystem will only be used in read-only mode
     * @throws IOException on errors reading, or on invalid data
     */
    public POIFSFileSystem(File file, boolean readOnly)
            throws IOException {
        this(null, file, readOnly, true);
    }

    /**
     * <p>Creates a POIFSFileSystem from an open <tt>FileChannel</tt>. This uses
     * less memory than creating from an <tt>InputStream</tt>. The stream will
     * be used in read-only mode.</p>
     *
     * <p>Note that with this constructor, you will need to call {@link #close()}
     * when you're done to have the underlying Channel closed, as the channel is
     * kept open during normal operation to read the data out.</p>
     *
     * @param channel the FileChannel from which to read the data
     * @throws IOException on errors reading, or on invalid data
     */
    public POIFSFileSystem(FileChannel channel)
            throws IOException {
        this(channel, true);
    }

    /**
     * <p>Creates a POIFSFileSystem from an open <tt>FileChannel</tt>. This uses
     * less memory than creating from an <tt>InputStream</tt>.</p>
     *
     * <p>Note that with this constructor, you will need to call {@link #close()}
     * when you're done to have the underlying Channel closed, as the channel is
     * kept open during normal operation to read the data out.</p>
     *
     * @param channel  the FileChannel from which to read or read/write the data
     * @param readOnly whether the POIFileSystem will only be used in read-only mode
     * @throws IOException on errors reading, or on invalid data
     */
    public POIFSFileSystem(FileChannel channel, boolean readOnly)
            throws IOException {
        this(channel, null, readOnly, false);
    }

    @SuppressWarnings("java:S2095")
    private POIFSFileSystem(FileChannel channel, File srcFile, boolean readOnly, boolean closeChannelOnError)
            throws IOException {
        this(false);

        try {
            // Initialize the datasource
            if (srcFile != null) {
                if (srcFile.length() == 0)
                    throw new EmptyFileException(srcFile);

                FileBackedDataSource d = new FileBackedDataSource(srcFile, readOnly);
                channel = d.getChannel();
                _data = d;
            } else {
                _data = new FileBackedDataSource(channel, readOnly);
            }

            // Get the header
            ByteBuffer headerBuffer = ByteBuffer.allocate(POIFSConstants.SMALLER_BIG_BLOCK_SIZE);
            IOUtils.readFully(channel, headerBuffer);

            // Have the header processed
            _header = new HeaderBlock(headerBuffer);

            // Now process the various entries
            readCoreContents();
        } catch (IOException | RuntimeException e) {
            // Comes from Iterators etc.
            // TODO Decide if we can handle these better whilst
            //  still sticking to the iterator contract
            if (closeChannelOnError && channel != null) {
                channel.close();
            }
            throw e;
        }
    }

    /**
     * Create a POIFSFileSystem from an <tt>InputStream</tt>.  Normally the stream is read until
     * EOF.  The stream is always closed.<p>
     * <p>
     * Some streams are usable after reaching EOF (typically those that return <code>true</code>
     * for <tt>markSupported()</tt>).  In the unlikely case that the caller has such a stream
     * <i>and</i> needs to use it after this constructor completes, a work around is to wrap the
     * stream in order to trap the <tt>close()</tt> call.  A convenience method (
     * <tt>createNonClosingInputStream()</tt>) has been provided for this purpose:
     * <pre>
     * InputStream wrappedStream = POIFSFileSystem.createNonClosingInputStream(is);
     * HSSFWorkbook wb = new HSSFWorkbook(wrappedStream);
     * is.reset();
     * doSomethingElse(is);
     * </pre>
     * Note also the special case of <tt>ByteArrayInputStream</tt> for which the <tt>close()</tt>
     * method does nothing.
     * <pre>
     * ByteArrayInputStream bais = ...
     * HSSFWorkbook wb = new HSSFWorkbook(bais); // calls bais.close() !
     * bais.reset(); // no problem
     * doSomethingElse(bais);
     * </pre>
     *
     * @param stream the InputStream from which to read the data
     * @throws IOException on errors reading, or on invalid data
     */

    public POIFSFileSystem(InputStream stream)
            throws IOException {
        this(false);

        boolean success = false;
        try (ReadableByteChannel channel = Channels.newChannel(stream)) {
            // Turn our InputStream into something NIO based

            // Get the header
            ByteBuffer headerBuffer = ByteBuffer.allocate(POIFSConstants.SMALLER_BIG_BLOCK_SIZE);
            IOUtils.readFully(channel, headerBuffer);

            // Have the header processed
            _header = new HeaderBlock(headerBuffer);

            // Sanity check the block count
            sanityCheckBlockCount(_header.getBATCount());

            // We need to buffer the whole file into memory when
            //  working with an InputStream.
            // The max possible size is when each BAT block entry is used
            long maxSize = BATBlock.calculateMaximumSize(_header);
            if (maxSize > Integer.MAX_VALUE) {
                throw new IllegalArgumentException("Unable read a >2gb file via an InputStream");
            }
            ByteBuffer data = ByteBuffer.allocate((int) maxSize);

            // Copy in the header
            headerBuffer.position(0);
            data.put(headerBuffer);
            data.position(headerBuffer.capacity());

            // Now read the rest of the stream
            IOUtils.readFully(channel, data);
            success = true;

            // Turn it into a DataSource
            _data = new ByteArrayBackedDataSource(data.array(), data.position());
        } finally {
            // As per the constructor contract, always close the stream
            closeInputStream(stream, success);
        }

        // Now process the various entries
        readCoreContents();
    }

    /**
     * @param stream  the stream to be closed
     * @param success <code>false</code> if an exception is currently being thrown in the calling method
     */
    private void closeInputStream(InputStream stream, boolean success) {
        try {
            stream.close();
        } catch (IOException e) {
            if (success) {
                throw new RuntimeException(e);
            }
            // else not success? Try block did not complete normally
            // just print stack trace and leave original ex to be thrown
            LOG.atError().withThrowable(e).log("can't close input stream");
        }
    }

    /**
     * Read and process the PropertiesTable and the
     * FAT / XFAT blocks, so that we're ready to
     * work with the file
     */
    private void readCoreContents() throws IOException {
        // Grab the block size
        bigBlockSize = _header.getBigBlockSize();

        // Each block should only ever be used by one of the
        //  FAT, XFAT or Property Table. Ensure it does
        ChainLoopDetector loopDetector = getChainLoopDetector();

        // Read the FAT blocks
        for (int fatAt : _header.getBATArray()) {
            readBAT(fatAt, loopDetector);
        }

        // Work out how many FAT blocks remain in the XFATs
        int remainingFATs = _header.getBATCount() - _header.getBATArray().length;

        // Now read the XFAT blocks, and the FATs within them
        BATBlock xfat;
        int nextAt = _header.getXBATIndex();
        for (int i = 0; i < _header.getXBATCount(); i++) {
            loopDetector.claim(nextAt);
            ByteBuffer fatData = getBlockAt(nextAt);
            xfat = BATBlock.createBATBlock(bigBlockSize, fatData);
            xfat.setOurBlockIndex(nextAt);
            nextAt = xfat.getValueAt(bigBlockSize.getXBATEntriesPerBlock());
            _xbat_blocks.add(xfat);

            // Process all the (used) FATs from this XFAT
            int xbatFATs = Math.min(remainingFATs, bigBlockSize.getXBATEntriesPerBlock());
            for (int j = 0; j < xbatFATs; j++) {
                int fatAt = xfat.getValueAt(j);
                if (fatAt == POIFSConstants.UNUSED_BLOCK || fatAt == POIFSConstants.END_OF_CHAIN) break;
                readBAT(fatAt, loopDetector);
            }
            remainingFATs -= xbatFATs;
        }

        // We're now able to load steams
        // Use this to read in the properties
        _property_table = new PropertyTable(_header, this);

        // Finally read the Small Stream FAT (SBAT) blocks
        BATBlock sfat;
        List<BATBlock> sbats = new ArrayList<>();
        _mini_store = new POIFSMiniStore(this, _property_table.getRoot(), sbats, _header);
        nextAt = _header.getSBATStart();
        for (int i = 0; i < _header.getSBATCount() && nextAt != POIFSConstants.END_OF_CHAIN; i++) {
            loopDetector.claim(nextAt);
            ByteBuffer fatData = getBlockAt(nextAt);
            sfat = BATBlock.createBATBlock(bigBlockSize, fatData);
            sfat.setOurBlockIndex(nextAt);
            sbats.add(sfat);
            nextAt = getNextBlock(nextAt);
        }
    }

    private void readBAT(int batAt, ChainLoopDetector loopDetector) throws IOException {
        loopDetector.claim(batAt);
        ByteBuffer fatData = getBlockAt(batAt);
        BATBlock bat = BATBlock.createBATBlock(bigBlockSize, fatData);
        bat.setOurBlockIndex(batAt);
        _bat_blocks.add(bat);
    }

    private BATBlock createBAT(int offset, boolean isBAT) throws IOException {
        // Create a new BATBlock
        BATBlock newBAT = BATBlock.createEmptyBATBlock(bigBlockSize, !isBAT);
        newBAT.setOurBlockIndex(offset);
        // Ensure there's a spot in the file for it
        ByteBuffer buffer = ByteBuffer.allocate(bigBlockSize.getBigBlockSize());
        // Header isn't in BATs
        long writeTo = ArithmeticUtils.mulAndCheck(1L + offset, bigBlockSize.getBigBlockSize());
        _data.write(buffer, writeTo);
        // All done
        return newBAT;
    }

    /**
     * Load the block at the given offset.
     */
    @Override
    protected ByteBuffer getBlockAt(final int offset) throws IOException {
        // The header block doesn't count, so add one
        long blockWanted = offset + 1L;
        long startAt = blockWanted * bigBlockSize.getBigBlockSize();
        try {
            return _data.read(bigBlockSize.getBigBlockSize(), startAt);
        } catch (IndexOutOfBoundsException e) {
            IndexOutOfBoundsException wrapped = new IndexOutOfBoundsException("Block " + offset + " not found");
            wrapped.initCause(e);
            throw wrapped;
        }
    }

    /**
     * Load the block at the given offset,
     * extending the file if needed
     */
    @Override
    protected ByteBuffer createBlockIfNeeded(final int offset) throws IOException {
        try {
            return getBlockAt(offset);
        } catch (IndexOutOfBoundsException e) {
            // The header block doesn't count, so add one
            long startAt = (offset + 1L) * bigBlockSize.getBigBlockSize();
            // Allocate and write
            ByteBuffer buffer = ByteBuffer.allocate(getBigBlockSize());
            _data.write(buffer, startAt);
            // Retrieve the properly backed block
            return getBlockAt(offset);
        }
    }

    /**
     * Returns the BATBlock that handles the specified offset,
     * and the relative index within it
     */
    @Override
    protected BATBlockAndIndex getBATBlockAndIndex(final int offset) {
        return BATBlock.getBATBlockAndIndex(
                offset, _header, _bat_blocks
        );
    }

    /**
     * Works out what block follows the specified one.
     */
    @Override
    protected int getNextBlock(final int offset) {
        BATBlockAndIndex bai = getBATBlockAndIndex(offset);
        return bai.getBlock().getValueAt(bai.getIndex());
    }

    /**
     * Changes the record of what block follows the specified one.
     */
    @Override
    protected void setNextBlock(final int offset, final int nextBlock) {
        BATBlockAndIndex bai = getBATBlockAndIndex(offset);
        bai.getBlock().setValueAt(
                bai.getIndex(), nextBlock
        );
    }

    /**
     * Finds a free block, and returns its offset.
     * This method will extend the file if needed, and if doing
     * so, allocate new FAT blocks to address the extra space.
     */
    @Override
    protected int getFreeBlock() throws IOException {
        int numSectors = bigBlockSize.getBATEntriesPerBlock();

        // First up, do we have any spare ones?
        int offset = 0;
        for (BATBlock bat : _bat_blocks) {
            if (bat.hasFreeSectors()) {
                // Claim one of them and return it
                for (int j = 0; j < numSectors; j++) {
                    int batValue = bat.getValueAt(j);
                    if (batValue == POIFSConstants.UNUSED_BLOCK) {
                        // Bingo
                        return offset + j;
                    }
                }
            }

            // Move onto the next BAT
            offset += numSectors;
        }

        // If we get here, then there aren't any free sectors
        //  in any of the BATs, so we need another BAT
        BATBlock bat = createBAT(offset, true);
        bat.setValueAt(0, POIFSConstants.FAT_SECTOR_BLOCK);
        _bat_blocks.add(bat);

        // Now store a reference to the BAT in the required place
        if (_header.getBATCount() >= 109) {
            // Needs to come from an XBAT
            BATBlock xbat = null;
            for (BATBlock x : _xbat_blocks) {
                if (x.hasFreeSectors()) {
                    xbat = x;
                    break;
                }
            }
            if (xbat == null) {
                // Oh joy, we need a new XBAT too...
                xbat = createBAT(offset + 1, false);
                // Allocate our new BAT as the first block in the XBAT
                xbat.setValueAt(0, offset);
                // And allocate the XBAT in the BAT
                bat.setValueAt(1, POIFSConstants.DIFAT_SECTOR_BLOCK);

                // Will go one place higher as XBAT added in
                offset++;

                // Chain it
                if (_xbat_blocks.size() == 0) {
                    _header.setXBATStart(offset);
                } else {
                    _xbat_blocks.get(_xbat_blocks.size() - 1).setValueAt(
                            bigBlockSize.getXBATEntriesPerBlock(), offset
                    );
                }
                _xbat_blocks.add(xbat);
                _header.setXBATCount(_xbat_blocks.size());
            } else {
                // Allocate our BAT in the existing XBAT with space
                for (int i = 0; i < bigBlockSize.getXBATEntriesPerBlock(); i++) {
                    if (xbat.getValueAt(i) == POIFSConstants.UNUSED_BLOCK) {
                        xbat.setValueAt(i, offset);
                        break;
                    }
                }
            }
        } else {
            // Store us in the header
            int[] newBATs = new int[_header.getBATCount() + 1];
            System.arraycopy(_header.getBATArray(), 0, newBATs, 0, newBATs.length - 1);
            newBATs[newBATs.length - 1] = offset;
            _header.setBATArray(newBATs);
        }
        _header.setBATCount(_bat_blocks.size());

        // The current offset stores us, but the next one is free
        return offset + 1;
    }

    protected long size() throws IOException {
        return _data.size();
    }

    @Override
    protected ChainLoopDetector getChainLoopDetector() throws IOException {
        return new ChainLoopDetector(_data.size());
    }

    /**
     * For unit testing only! Returns the underlying
     * properties table
     */
    PropertyTable _get_property_table() {
        return _property_table;
    }

    /**
     * Returns the MiniStore, which performs a similar low
     * level function to this, except for the small blocks.
     */
    POIFSMiniStore getMiniStore() {
        return _mini_store;
    }

    /**
     * add a new POIFSDocument to the FileSytem
     *
     * @param document the POIFSDocument being added
     */
    void addDocument(final POIFSDocument document) {
        _property_table.addProperty(document.getDocumentProperty());
    }

    /**
     * add a new DirectoryProperty to the FileSystem
     *
     * @param directory the DirectoryProperty being added
     */
    void addDirectory(final DirectoryProperty directory) {
        _property_table.addProperty(directory);
    }

    /**
     * Create a new document to be added to the root directory
     *
     * @param stream the InputStream from which the document's data
     *               will be obtained
     * @param name   the name of the new POIFSDocument
     * @return the new DocumentEntry
     * @throws IOException on error creating the new POIFSDocument
     */

    public DocumentEntry createDocument(final InputStream stream,
                                        final String name)
            throws IOException {
        return getRoot().createDocument(name, stream);
    }

    /**
     * create a new DocumentEntry in the root entry; the data will be
     * provided later
     *
     * @param name   the name of the new DocumentEntry
     * @param size   the size of the new DocumentEntry
     * @param writer the writer of the new DocumentEntry
     * @return the new DocumentEntry
     * @throws IOException if the writer exceeds the given size
     */
    public DocumentEntry createDocument(final String name, final int size, final POIFSWriterListener writer)
            throws IOException {
        return getRoot().createDocument(name, size, writer);
    }

    /**
     * create a new DirectoryEntry in the root directory
     *
     * @param name the name of the new DirectoryEntry
     * @return the new DirectoryEntry
     * @throws IOException on name duplication
     */

    public DirectoryEntry createDirectory(final String name)
            throws IOException {
        return getRoot().createDirectory(name);
    }

    /**
     * Set the contents of a document in the root directory,
     * creating if needed, otherwise updating
     *
     * @param stream the InputStream from which the document's data
     *               will be obtained
     * @param name   the name of the new or existing POIFSDocument
     * @return the new or updated DocumentEntry
     * @throws IOException on error populating the POIFSDocument
     */
    @SuppressWarnings("UnusedReturnValue")
    public DocumentEntry createOrUpdateDocument(final InputStream stream, final String name)
            throws IOException {
        return getRoot().createOrUpdateDocument(name, stream);
    }

    /**
     * Does the filesystem support an in-place write via
     * {@link #writeFilesystem()} ? If false, only writing out to
     * a brand new file via {@link #writeFilesystem(OutputStream)}
     * is supported.
     */
    public boolean isInPlaceWriteable() {
        return (_data instanceof FileBackedDataSource) && ((FileBackedDataSource) _data).isWriteable();
    }

    /**
     * Write the filesystem out to the open file. Will thrown an
     * {@link IllegalArgumentException} if opened from an
     * {@link InputStream}.
     *
     * @throws IOException thrown on errors writing to the stream
     */
    public void writeFilesystem() throws IOException {
        if (!(_data instanceof FileBackedDataSource)) {
            throw new IllegalArgumentException(
                    "POIFS opened from an inputstream, so writeFilesystem() may " +
                            "not be called. Use writeFilesystem(OutputStream) instead"
            );
        }
        if (!((FileBackedDataSource) _data).isWriteable()) {
            throw new IllegalArgumentException(
                    "POIFS opened in read only mode, so writeFilesystem() may " +
                            "not be called. Open the FileSystem in read-write mode first"
            );
        }
        syncWithDataSource();
    }

    /**
     * Write the filesystem out
     *
     * @param stream the OutputStream to which the filesystem will be
     *               written
     * @throws IOException thrown on errors writing to the stream
     */
    public void writeFilesystem(final OutputStream stream) throws IOException {
        // Have the datasource updated
        syncWithDataSource();

        // Now copy the contents to the stream
        _data.copyTo(stream);
    }

    /**
     * Has our in-memory objects write their state
     * to their backing blocks
     */
    private void syncWithDataSource() throws IOException {
        // Mini Stream + SBATs first, as mini-stream details have
        //  to be stored in the Root Property
        _mini_store.syncWithDataSource();

        // Properties
        POIFSStream propStream = new POIFSStream(this, _header.getPropertyStart());
        _property_table.preWrite();
        _property_table.write(propStream);
        // _header.setPropertyStart has been updated on write ...

        // HeaderBlock
        ByteArrayOutputStream baos = new ByteArrayOutputStream(
                _header.getBigBlockSize().getBigBlockSize()
        );
        _header.writeData(baos);
        getBlockAt(-1).put(baos.toByteArray());


        // BATs
        for (BATBlock bat : _bat_blocks) {
            ByteBuffer block = getBlockAt(bat.getOurBlockIndex());
            bat.writeData(block);
        }
        // XBats
        for (BATBlock bat : _xbat_blocks) {
            ByteBuffer block = getBlockAt(bat.getOurBlockIndex());
            bat.writeData(block);
        }
    }

    /**
     * Closes the FileSystem, freeing any underlying files, streams
     * and buffers. After this, you will be unable to read or
     * write from the FileSystem.
     */
    @Override
    public void close() throws IOException {
        _data.close();
    }

    /**
     * read in a file and write it back out again
     *
     * @param args names of the files; arg[ 0 ] is the input file,
     *             arg[ 1 ] is the output file
     */
    public static void main(String[] args) throws IOException {
        if (args.length != 2) {
            System.err.println(
                    "two arguments required: input filename and output filename");
            System.exit(1);
        }

        try (FileInputStream istream = new FileInputStream(args[0])) {
            try (FileOutputStream ostream = new FileOutputStream(args[1])) {
                try (POIFSFileSystem fs = new POIFSFileSystem(istream)) {
                    fs.writeFilesystem(ostream);
                }
            }
        }
    }

    /**
     * Get the root entry
     *
     * @return the root entry
     */
    public DirectoryNode getRoot() {
        if (_root == null) {
            _root = new DirectoryNode(_property_table.getRoot(), this, null);
        }
        return _root;
    }

    /**
     * open a document in the root entry's list of entries
     *
     * @param documentName the name of the document to be opened
     * @return a newly opened DocumentInputStream
     * @throws IOException if the document does not exist or the
     *                     name is that of a DirectoryEntry
     */
    public DocumentInputStream createDocumentInputStream(
            final String documentName) throws IOException {
        return getRoot().createDocumentInputStream(documentName);
    }

    /**
     * remove an entry
     *
     * @param entry to be removed
     */
    void remove(EntryNode entry) throws IOException {
        // If it's a document, free the blocks
        if (entry instanceof DocumentEntry) {
            POIFSDocument doc = new POIFSDocument((DocumentProperty) entry.getProperty(), this);
            doc.free();
        }

        // Now zap it from the properties list
        _property_table.removeProperty(entry.getProperty());
    }

    /* ********** START begin implementation of POIFSViewable ********** */

    /**
     * Get an array of objects, some of which may implement
     * POIFSViewable
     *
     * @return an array of Object; may not be null, but may be empty
     */
    @Override
    public Object[] getViewableArray() {
        if (preferArray()) {
            return getRoot().getViewableArray();
        }

        return new Object[0];
    }

    /**
     * Get an Iterator of objects, some of which may implement
     * POIFSViewable
     *
     * @return an Iterator; may not be null, but may have an empty
     * back end store
     */

    @Override
    public Iterator<Object> getViewableIterator() {
        if (!preferArray()) {
            return getRoot().getViewableIterator();
        }

        return Collections.emptyIterator();
    }

    /**
     * Give viewers a hint as to whether to call getViewableArray or
     * getViewableIterator
     *
     * @return true if a viewer should call getViewableArray, false if
     * a viewer should call getViewableIterator
     */

    @Override
    public boolean preferArray() {
        return getRoot().preferArray();
    }

    /**
     * Provides a short description of the object, to be used when a
     * POIFSViewable object has not provided its contents.
     *
     * @return short description
     */

    @Override
    public String getShortDescription() {
        return "POIFS FileSystem";
    }

    /* **********  END  begin implementation of POIFSViewable ********** */

    /**
     * @return The Big Block size, normally 512 bytes, sometimes 4096 bytes
     */
    public int getBigBlockSize() {
        return bigBlockSize.getBigBlockSize();
    }

    /**
     * @return The Big Block size, normally 512 bytes, sometimes 4096 bytes
     */
    @SuppressWarnings("WeakerAccess")
    public POIFSBigBlockSize getBigBlockSizeDetails() {
        return bigBlockSize;
    }

    /**
     * Creates a new {@link POIFSFileSystem} in a new {@link File}.
     * Use {@link #POIFSFileSystem(File)} to open an existing File,
     * this should only be used to create a new empty filesystem.
     *
     * @param file The file to create and open
     * @return The created and opened {@link POIFSFileSystem}
     */
    public static POIFSFileSystem create(File file) throws IOException {
        // Create a new empty POIFS in the file
        try (POIFSFileSystem tmp = new POIFSFileSystem();
             OutputStream out = new FileOutputStream(file)) {
            tmp.writeFilesystem(out);
        }

        // Open it up again backed by the file
        return new POIFSFileSystem(file, false);
    }

    @Override
    protected int getBlockStoreBlockSize() {
        return getBigBlockSize();
    }

    @Internal
    public PropertyTable getPropertyTable() {
        return _property_table;
    }

    @Internal
    public HeaderBlock getHeaderBlock() {
        return _header;
    }

    @Override
    protected void releaseBuffer(ByteBuffer buffer) {
        if (_data instanceof FileBackedDataSource) {
            ((FileBackedDataSource)_data).releaseBuffer(buffer);
        }
    }

    private static void sanityCheckBlockCount(int block_count) throws IOException {
        if (block_count <= 0) {
            throw new IOException(
                    "Illegal block count; minimum count is 1, got " +
                            block_count + " instead"
            );
        }
        if (block_count > MAX_BLOCK_COUNT) {
            throw new IOException(
                    "Block count " + block_count +
                            " is too high. POI maximum is " + MAX_BLOCK_COUNT + "."
            );
        }
    }

}
