/*
 * 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
 */

const Utils = require("./../../../unisharp/Utils");
const Stream = require("./../../../unisharp/Stream");
const FileStream = require("./../../../unisharp/FileStream");

// Base stream for retrival data from a Compound File.
class CompoundFileStream extends Stream {
    
    get storage() {
        return this.m_Storage;
    }
    
    get system() {
        return this.storage.system;
    }
    
    get pageSize() {
        return this.m_PageSize;
    }
    
    constructor(_storage, _pageSize) {
        super();
        this.m_Storage = null;
        this.m_Position = 0;
        this.m_Length = 0;
        this.m_PageSize = 0;
        this.m_Page = null;
        this.m_PageIndex = -1;
        this.m_Storage = _storage;
        this.m_Position = 0;
        this.m_Length = _storage.length;
        this.m_PageSize = _pageSize;
    }
    
    get canRead() {
        return true;
    }
    
    get canSeek() {
        return true;
    }
    
    get canWrite() {
        return false;
    }
    
    flush() {
        
    }
    
    get length() {
        return this.m_Length;
    }
    
    get position() {
        return this.m_Position;
    }
    set position(value) {
        this.seek(value, 0);
        return value;
    }
    
    read(buffer, offset, count) {
        if (count <= 0) 
            return count;
        if (this.m_Position >= this.m_Length) 
            return 0;
        let _canRead = (count > ((this.m_Length - this.m_Position)) ? (this.m_Length - this.m_Position) : count);
        try {
            let pageStartPosition = this.m_PageSize * this.m_PageIndex;
            let pageEndPosition = pageStartPosition;
            if (this.m_Page !== null) 
                pageEndPosition += this.m_Page.length;
            if ((this.m_Position < pageStartPosition) || (this.m_Position + _canRead) > pageEndPosition) {
                let cachedPage = this.m_Page;
                let cachedPageIndex = this.m_PageIndex;
                let startPageIndex = (Utils.intDiv(this.m_Position, this.m_PageSize));
                let lastPageIndex = (Utils.intDiv(((this.m_Position + _canRead) - 1), this.m_PageSize));
                if (startPageIndex !== cachedPageIndex) {
                    this.m_Page = this.getPageData(startPageIndex);
                    this.m_PageIndex = startPageIndex;
                }
                let startPageOffset = (this.m_Position - (startPageIndex * this.m_PageSize));
                let startPageTail = this.m_Page.length - startPageOffset;
                if (startPageTail >= _canRead) {
                    for(let iii = 0; iii < (_canRead); iii++) buffer[(offset) + iii] = this.m_Page[(startPageOffset) + iii];
                    this.m_Position += _canRead;
                }
                else {
                    for(let iii = 0; iii < (startPageTail); iii++) buffer[(offset) + iii] = this.m_Page[(startPageOffset) + iii];
                    offset += startPageTail;
                    this.m_Position += startPageTail;
                    let leftToRead = _canRead - startPageTail;
                    for (let i = startPageIndex + 1; i < lastPageIndex; i++) {
                        if (cachedPageIndex === i) {
                            this.m_Page = cachedPage;
                            this.m_PageIndex = cachedPageIndex;
                        }
                        else {
                            this.m_Page = this.getPageData(i);
                            this.m_PageIndex = i;
                        }
                        for(let iii = 0; iii < (this.m_Page.length); iii++) buffer[(offset) + iii] = this.m_Page[(0) + iii];
                        offset += this.m_Page.length;
                        this.m_Position += this.m_Page.length;
                        leftToRead -= this.m_Page.length;
                    }
                    if (cachedPageIndex === lastPageIndex) {
                        this.m_Page = cachedPage;
                        this.m_PageIndex = cachedPageIndex;
                    }
                    else {
                        this.m_Page = this.getPageData(lastPageIndex);
                        this.m_PageIndex = lastPageIndex;
                    }
                    for(let iii = 0; iii < (leftToRead); iii++) buffer[(offset) + iii] = this.m_Page[(0) + iii];
                    this.m_Position += leftToRead;
                }
            }
            else {
                for(let iii = 0; iii < (_canRead); iii++) buffer[(offset) + iii] = this.m_Page[((this.m_Position - pageStartPosition)) + iii];
                this.m_Position += _canRead;
            }
        } catch (ex) {
            return -1;
        }
        return _canRead;
    }
    
    getPageData(pageIndex) {
        return null;
    }
    
    seek(offset, origin) {
        switch (origin) { 
        case 0: {
            this.m_Position = offset;
            break;
        }
        case 1: {
            this.m_Position += (offset);
            break;
        }
        case 2: {
            this.m_Position = (this.length + offset);
            break;
        }
        }
        return this.m_Position;
    }
    
    setLength(value) {
        
    }
    
    write(buffer, offset, count) {
        
    }
    
    dispose(disposing) {
        super.dispose(disposing);
        if (disposing) {
            this.m_Storage = null;
            this.m_Page = null;
        }
    }
}


module.exports = CompoundFileStream