/*
 * SDK Pullenti Unitext, version 4.33, fabruary 2026. Copyright (c) 2013-2026, Pullenti. All rights reserved. 
 * Non-Commercial Freeware and Commercial Software. 
 * This class is generated using the converter Unisharping (www.unisharping.ru) from Pullenti C# project. 
 * The latest version of the code is available on the site www.pullenti.ru
 */

package com.pullenti.unitext.internal.word;

// Compound File Storage.
public class CompoundFileStorage {

    private CompoundFileSystem m_System;

    private int m_StreamID;

    private CFDirectoryEntry m_Entry;

    private Iterable<Integer> m_Ancestors;

    public CompoundFileSystem getSystem() {
        return m_System;
    }


    public CFDirectoryEntry getEntry() {
        return m_Entry;
    }


    public ExtendedName getName() throws IllegalArgumentException {
        return new ExtendedName(null, m_Entry.name, 0, m_Entry.name.length - 1);
    }


    public int getLength() {
        return (int)m_Entry.streamSize;
    }


    public CompoundFileObjectType getObjectType() {
        return CompoundFileObjectType.of(Byte.toUnsignedInt(m_Entry.objectType));
    }


    public CompoundFileStorage(CompoundFileSystem _system, int streamID, Iterable<Integer> ancestors) throws Exception, java.io.IOException {
        this.m_System = _system;
        this.m_StreamID = streamID;
        this.m_Ancestors = ancestors;
        this.initialize();
    }

    private void initialize() throws Exception, java.io.IOException {
        int off = this.getStreamOffset();
        m_Entry = ReaderUtils.readDirectoryEntry(this.getSystem().getBaseStream(), off, this.getSystem().isVersion3());
        ReaderUtils.validateDirectoryEntry(m_Entry);
    }

    private int getStreamOffset() throws Exception, java.io.IOException {
        int offsetWithinLogicalStream = ((int)m_StreamID) * ReaderUtils.directoryEntrySize;
        if (!getSystem().isVersion3() && ((offsetWithinLogicalStream >> this.getSystem().getHeader().sectorShift)) >= (Integer.toUnsignedLong(getSystem().getHeader().directorySectorsCount))) 
            throw new Exception("Stream ID out of range");
        return getSystem().toPhysicalStreamOffset(this.getSystem().getHeader().firstDirectorySectorLocation, offsetWithinLogicalStream);
    }

    private void appendChild(java.util.ArrayList<CompoundFileStorage> collection, int streamID, java.util.HashMap<Integer, CompoundFileStorage> processed, Iterable<Integer> ancestors) throws Exception, java.io.IOException {
        if (processed.containsKey(streamID)) 
            throw new Exception("Circular structure: siblings");
        CompoundFileStorage item = new CompoundFileStorage(getSystem(), streamID, ancestors);
        processed.put(streamID, item);
        if (Integer.compareUnsigned(item.getEntry().leftSiblingID, DirectoryStreamIds.nOSTREAM) != 0) 
            this.appendChild(collection, item.getEntry().leftSiblingID, processed, ancestors);
        if (item.getObjectType() != CompoundFileObjectType.UNKNOWN) 
            collection.add(item);
        if (Integer.compareUnsigned(item.getEntry().rightSiblingID, DirectoryStreamIds.nOSTREAM) != 0) 
            this.appendChild(collection, item.getEntry().rightSiblingID, processed, ancestors);
    }

    public Iterable<CompoundFileStorage> getStorages() throws Exception, java.io.IOException {
        java.util.ArrayList<CompoundFileStorage> entries = new java.util.ArrayList<CompoundFileStorage>();
        java.util.HashMap<Integer, CompoundFileStorage> processed = new java.util.HashMap<Integer, CompoundFileStorage>();
        int childID = m_Entry.childID;
        if (Integer.compareUnsigned(childID, DirectoryStreamIds.nOSTREAM) != 0) {
            java.util.ArrayList<Integer> newAncestors = new java.util.ArrayList<Integer>();
            newAncestors.add(m_StreamID);
            com.pullenti.unisharp.Utils.addToArrayList(newAncestors, m_Ancestors);
            if (newAncestors.contains(childID)) 
                throw new Exception("Circular structure: ancestors");
            this.appendChild(entries, childID, processed, m_Ancestors);
        }
        return entries;
    }

    public CompoundFileStorage findStorage(ExtendedName _name) throws IllegalArgumentException, Exception, java.io.IOException {
        for (CompoundFileStorage storage : this.getStorages()) {
            if (ExtendedName.ooEq(storage.getName(), _name)) 
                return storage;
        }
        return null;
    }

    public com.pullenti.unisharp.Stream createStream() throws Exception, UnsupportedOperationException, java.io.IOException {
        if (m_Entry.objectType == DirectoryObjectTypes.stream) {
            if (Long.compareUnsigned(Integer.toUnsignedLong(m_Entry.streamSize), (long)getSystem().getBaseStream().length()) > 0) 
                throw new Exception("Stream length");
            if (Integer.compareUnsigned(m_Entry.streamSize, getSystem().getHeader().miniStreamCutoffSize) < 0) 
                return new MiniFATStream(this);
            else 
                return new FATStream(this);
        }
        else 
            throw new UnsupportedOperationException();
    }
    public CompoundFileStorage() {
    }
}
