/*
 * 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.zip;

/**
 * A <see cref="PartialInputStream"/> is an <see cref="InflaterInputStream"/> 
 * whose data is only a part or subsection of a file.
 */
public class PartialInputStream extends com.pullenti.unisharp.Stream {

    /**
     * Initialise a new instance of the <see cref="PartialInputStream"/> class.
     * @param zipFile The <see cref="ZipFile"/> containing the underlying stream to use for IO.
     * @param start The start of the partial data.
     * @param _length The length of the partial data.
     */
    public PartialInputStream(ZipFile zipFile, int start, int _length) {
        super();
        m_Start = start;
        m_Length = _length;
        m_ZipFile = zipFile;
        m_BaseStream = m_ZipFile.m_BaseStream;
        m_ReadPos = start;
        m_End = start + _length;
    }

    /**
     * Read a byte from this stream.
     * @return Returns the byte read or -1 on end of stream.
     */
    @Override
    public int read() throws java.io.IOException {
        if (m_ReadPos >= m_End) 
            return -1;
        m_BaseStream.seek((long)(m_ReadPos++), 0);
        return m_BaseStream.read();
    }

    /**
     * Close this <see cref="PartialInputStream">partial input stream</see>.
     */
    @Override
    public void close() {
    }

    /**
     * Reads a sequence of bytes from the current stream and advances the position within the stream by the number of bytes read.
     * @param buffer An array of bytes. When this method returns, the buffer contains the specified byte array with the values between offset and (offset + count - 1) replaced by the bytes read from the current source.
     * @param offset The zero-based byte offset in buffer at which to begin storing the data read from the current stream.
     * @param count The maximum number of bytes to be read from the current stream.
     * @return The total number of bytes read into the buffer. This can be less than the number of bytes requested if that many bytes are not currently available, or zero (0) if the end of the stream has been reached.
     */
    @Override
    public int read(byte[] buffer, int offset, int count) throws java.io.IOException {
        if (count > (m_End - m_ReadPos)) {
            count = (m_End - m_ReadPos);
            if (count == 0) 
                return 0;
        }
        m_BaseStream.seek((long)m_ReadPos, 0);
        int readCount = m_BaseStream.read(buffer, offset, count);
        if (readCount > 0) 
            m_ReadPos += readCount;
        return readCount;
    }

    /**
     * Writes a sequence of bytes to the current stream and advances the current position within this stream by the number of bytes written.
     * @param buffer An array of bytes. This method copies count bytes from buffer to the current stream.
     * @param offset The zero-based byte offset in buffer at which to begin copying bytes to the current stream.
     * @param count The number of bytes to be written to the current stream.
     */
    @Override
    public void write(byte[] buffer, int offset, int count) throws java.io.IOException {
        throw new java.io.IOException("Not supported");
    }

    /**
     * When overridden in a derived class, sets the length of the current stream.
     * @param value The desired length of the current stream in bytes.
     */
    @Override
    public void setLength(long value) throws java.io.IOException {
        throw new java.io.IOException("Not supported");
    }

    /**
     * When overridden in a derived class, sets the position within the current stream.
     * @param offset A byte offset relative to the origin parameter.
     * @param origin A value of type <see cref="T:System.IO.SeekOrigin"></see> indicating the reference point used to obtain the new position.
     * @return The new position within the current stream.
     */
    @Override
    public long seek(long offset, int origin) throws java.io.IOException {
        int newPos = m_ReadPos;
        switch (origin) { 
        case 0:
            newPos = m_Start + ((int)offset);
            break;
        case 1:
            newPos = m_ReadPos + ((int)offset);
            break;
        case 2:
            newPos = m_End + ((int)offset);
            break;
    }
    if (newPos < m_Start) 
        throw new java.io.IOException("Negative position is invalid");
    if (newPos >= m_End) 
        throw new java.io.IOException("Cannot seek past end");
    m_ReadPos = newPos;
    return (long)m_ReadPos;
    }

    /**
     * Clears all buffers for this stream and causes any buffered data to be written to the underlying device.
     */
    @Override
    public void flush() {
    }

    @Override
    public long getPosition() {
        return (long)(m_ReadPos - m_Start);
    }

    @Override
    public long setPosition(long value) throws java.io.IOException {
        int newPos = m_Start + ((int)value);
        if (newPos < m_Start) 
            throw new java.io.IOException("Negative position is invalid");
        if (newPos >= m_End) 
            throw new java.io.IOException("Cannot seek past end");
        m_ReadPos = newPos;
        return value;
    }


    @Override
    public long length() {
        return (long)m_Length;
    }


    @Override
    public boolean canWrite() {
        return false;
    }


    @Override
    public boolean canSeek() {
        return true;
    }


    @Override
    public boolean canRead() {
        return true;
    }


    private ZipFile m_ZipFile;

    private com.pullenti.unisharp.Stream m_BaseStream;

    private int m_Start;

    private int m_Length;

    private int m_ReadPos;

    private int m_End;
    public PartialInputStream() {
        super();
    }
}
