/* ====================================================================
   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.hssf.record.aggregates;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.apache.poi.hssf.model.RecordStream;
import org.apache.poi.hssf.record.*;
import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.formula.FormulaShifter;

/**
 *
 * @author  andy
 * @author Jason Height (jheight at chariot dot net dot au)
 */
public final class RowRecordsAggregate extends RecordAggregate {
    private int _firstrow = -1;
    private int _lastrow  = -1;
    private final Map<Integer, RowRecord> _rowRecords;
    private final ValueRecordsAggregate _valuesAgg;
    private final List<Record> _unknownRecords;
    private final SharedValueManager _sharedValueManager;

    // Cache values to speed up performance of
    // getStartRowNumberForBlock / getEndRowNumberForBlock, see Bugzilla 47405
    private RowRecord[] _rowRecordValues = null;

    /** Creates a new instance of ValueRecordsAggregate */
    public RowRecordsAggregate() {
        this(SharedValueManager.createEmpty());
    }
    private RowRecordsAggregate(SharedValueManager svm) {
        if (svm == null) {
            throw new IllegalArgumentException("SharedValueManager must be provided.");
        }
        _rowRecords = new TreeMap<Integer, RowRecord>();
        _valuesAgg = new ValueRecordsAggregate();
        _unknownRecords = new ArrayList<Record>();
        _sharedValueManager = svm;
    }

    /**
     * @param rs record stream with all {@link SharedFormulaRecord}
     * {@link ArrayRecord}, {@link TableRecord} {@link MergeCellsRecord} Records removed
     * @param svm an initialised {@link SharedValueManager} (from the shared formula, array
     * and table records of the current sheet).  Never <code>null</code>.
     */
    public RowRecordsAggregate(RecordStream rs, SharedValueManager svm) {
        this(svm);
        while(rs.hasNext()) {
            Record rec = rs.getNext();
            switch (rec.getSid()) {
                case RowRecord.sid:
                    insertRow((RowRecord) rec);
                    continue;
                case DConRefRecord.sid:
                    addUnknownRecord(rec);
                    continue;
                case DBCellRecord.sid:
                    // end of 'Row Block'.  Should only occur after cell records
                    // ignore DBCELL records because POI generates them upon re-serialization
                    continue;
            }
            if (rec instanceof UnknownRecord) {
                // might need to keep track of where exactly these belong
                addUnknownRecord(rec);
                while (rs.peekNextSid() == ContinueRecord.sid) {
                    addUnknownRecord(rs.getNext());
                }
                continue;
            }
            if (rec instanceof MulBlankRecord) {
                _valuesAgg.addMultipleBlanks((MulBlankRecord) rec);
                continue;
            }
            if (!(rec instanceof CellValueRecordInterface)) {
                throw new RuntimeException("Unexpected record type (" + rec.getClass().getName() + ")");
            }
            _valuesAgg.construct((CellValueRecordInterface)rec, rs, svm);
        }
    }
    /**
     * Handles UnknownRecords which appear within the row/cell records
     */
    private void addUnknownRecord(Record rec) {
        // ony a few distinct record IDs are encountered by the existing POI test cases:
        // 0x1065 // many
        // 0x01C2 // several
        // 0x0034 // few
        // No documentation could be found for these

        // keep the unknown records for re-serialization
        _unknownRecords.add(rec);
    }
    public void insertRow(RowRecord row) {
        // Integer integer = Integer.valueOf(row.getRowNumber());
        _rowRecords.put(Integer.valueOf(row.getRowNumber()), row);
        // Clear the cached values
        _rowRecordValues = null; 
        if ((row.getRowNumber() < _firstrow) || (_firstrow == -1)) {
            _firstrow = row.getRowNumber();
        }
        if ((row.getRowNumber() > _lastrow) || (_lastrow == -1)) {
            _lastrow = row.getRowNumber();
        }
    }

    public void removeRow(RowRecord row) {
        int rowIndex = row.getRowNumber();
        _valuesAgg.removeAllCellsValuesForRow(rowIndex);
        Integer key = Integer.valueOf(rowIndex);
        RowRecord rr = _rowRecords.remove(key);
        if (rr == null) {
            throw new RuntimeException("Invalid row index (" + key.intValue() + ")");
        }
        if (row != rr) {
            _rowRecords.put(key, rr);
            throw new RuntimeException("Attempt to remove row that does not belong to this sheet");
        }
        
        // Clear the cached values
        _rowRecordValues = null;
    }

    public RowRecord getRow(int rowIndex) {
        int maxrow = SpreadsheetVersion.EXCEL97.getLastRowIndex();
        if (rowIndex < 0 || rowIndex > maxrow) {
            throw new IllegalArgumentException("The row number must be between 0 and " + maxrow + ", but had: " + rowIndex);
        }
        return _rowRecords.get(Integer.valueOf(rowIndex));
    }

    public int getPhysicalNumberOfRows()
    {
        return _rowRecords.size();
    }

    public int getFirstRowNum()
    {
        return _firstrow;
    }

    public int getLastRowNum()
    {
        return _lastrow;
    }

    /** Returns the number of row blocks.
     * <p/>The row blocks are goupings of rows that contain the DBCell record
     * after them
     */
    public int getRowBlockCount() {
        int size = _rowRecords.size()/DBCellRecord.BLOCK_SIZE;
        if ((_rowRecords.size() % DBCellRecord.BLOCK_SIZE) != 0)
            size++;
        return size;
    }

    private int getRowBlockSize(int block) {
        return RowRecord.ENCODED_SIZE * getRowCountForBlock(block);
    }

    /** Returns the number of physical rows within a block*/
    public int getRowCountForBlock(int block) {
        int startIndex = block * DBCellRecord.BLOCK_SIZE;
        int endIndex = startIndex + DBCellRecord.BLOCK_SIZE - 1;
        if (endIndex >= _rowRecords.size())
            endIndex = _rowRecords.size()-1;

        return endIndex-startIndex+1;
    }

    /** Returns the physical row number of the first row in a block*/
    private int getStartRowNumberForBlock(int block) {
        int startIndex = block * DBCellRecord.BLOCK_SIZE;

        if (_rowRecordValues == null) {
            _rowRecordValues = _rowRecords.values().toArray(new RowRecord[_rowRecords.size()]);
        }

        try {
            return _rowRecordValues[startIndex].getRowNumber();
        } catch(ArrayIndexOutOfBoundsException e) {
            throw new RuntimeException("Did not find start row for block " + block);
        }
    }

    /** Returns the physical row number of the end row in a block*/
    private int getEndRowNumberForBlock(int block) {
        int endIndex = ((block + 1)*DBCellRecord.BLOCK_SIZE)-1;
        if (endIndex >= _rowRecords.size())
            endIndex = _rowRecords.size()-1;

        if (_rowRecordValues == null){
            _rowRecordValues = _rowRecords.values().toArray(new RowRecord[_rowRecords.size()]);
        }

        try {
            return _rowRecordValues[endIndex].getRowNumber();
        } catch(ArrayIndexOutOfBoundsException e) {
            throw new RuntimeException("Did not find end row for block " + block);
      }
    }

    private int visitRowRecordsForBlock(int blockIndex, RecordVisitor rv) {
        final int startIndex = blockIndex*DBCellRecord.BLOCK_SIZE;
        final int endIndex = startIndex + DBCellRecord.BLOCK_SIZE;

        Iterator<RowRecord> rowIterator = _rowRecords.values().iterator();

        //Given that we basically iterate through the rows in order,
        //For a performance improvement, it would be better to return an instance of
        //an iterator and use that instance throughout, rather than recreating one and
        //having to move it to the right position.
        int i=0;
        for (;i<startIndex;i++)
          rowIterator.next();
        int result = 0;
        while(rowIterator.hasNext() && (i++ < endIndex)) {
          Record rec = rowIterator.next();
          result += rec.getRecordSize();
          rv.visitRecord(rec);
        }
        return result;
    }

    @Override
    public void visitContainedRecords(RecordVisitor rv) {

        PositionTrackingVisitor stv = new PositionTrackingVisitor(rv, 0);
        //DBCells are serialized before row records.
        final int blockCount = getRowBlockCount();
        for (int blockIndex = 0; blockIndex < blockCount; blockIndex++) {
            // Serialize a block of rows.
            // Hold onto the position of the first row in the block
            int pos=0;
            // Hold onto the size of this block that was serialized
            final int rowBlockSize = visitRowRecordsForBlock(blockIndex, rv);
            pos += rowBlockSize;
            // Serialize a block of cells for those rows
            final int startRowNumber = getStartRowNumberForBlock(blockIndex);
            final int endRowNumber = getEndRowNumberForBlock(blockIndex);
            DBCellRecord.Builder dbcrBuilder = new DBCellRecord.Builder();
            // Note: Cell references start from the second row...
            int cellRefOffset = (rowBlockSize - RowRecord.ENCODED_SIZE);
            for (int row = startRowNumber; row <= endRowNumber; row++) {
                if (_valuesAgg.rowHasCells(row)) {
                    stv.setPosition(0);
                    _valuesAgg.visitCellsForRow(row, stv);
                    int rowCellSize = stv.getPosition();
                    pos += rowCellSize;
                    // Add the offset to the first cell for the row into the
                    // DBCellRecord.
                    dbcrBuilder.addCellOffset(cellRefOffset);
                    cellRefOffset = rowCellSize;
                }
            }
            // Calculate Offset from the start of a DBCellRecord to the first Row
            rv.visitRecord(dbcrBuilder.build(pos));
        }
        for (Record _unknownRecord : _unknownRecords) {
            // Potentially breaking the file here since we don't know exactly where to write these records
            rv.visitRecord(_unknownRecord);
        }
    }

    public Iterator<RowRecord> getIterator() {
        return _rowRecords.values().iterator();
    }

    public int findStartOfRowOutlineGroup(int row) {
        // Find the start of the group.
        RowRecord rowRecord = this.getRow( row );
        int level = rowRecord.getOutlineLevel();
        int currentRow = row;
        while (currentRow >= 0 && this.getRow( currentRow ) != null) {
            rowRecord = this.getRow( currentRow );
            if (rowRecord.getOutlineLevel() < level) {
                return currentRow + 1;
            }
            currentRow--;
        }

        return currentRow + 1;
    }

    public int findEndOfRowOutlineGroup(int row) {
        int level = getRow( row ).getOutlineLevel();
        int currentRow;
        for (currentRow = row; currentRow < getLastRowNum(); currentRow++) {
            if (getRow(currentRow) == null || getRow(currentRow).getOutlineLevel() < level) {
                break;
            }
        }

        return currentRow-1;
    }

    /**
     * Hide all rows at or below the current outline level
     * @return index of the <em>next<em> row after the last row that gets hidden
     */
    private int writeHidden(RowRecord pRowRecord, int row) {
        int rowIx = row;
        RowRecord rowRecord = pRowRecord;
        int level = rowRecord.getOutlineLevel();
        while (rowRecord != null && getRow(rowIx).getOutlineLevel() >= level) {
            rowRecord.setZeroHeight(true);
            rowIx++;
            rowRecord = getRow(rowIx);
        }
        return rowIx;
    }

    public void collapseRow(int rowNumber) {

        // Find the start of the group.
        int startRow = findStartOfRowOutlineGroup(rowNumber);
        RowRecord rowRecord = getRow(startRow);

        // Hide all the columns until the end of the group
        int nextRowIx = writeHidden(rowRecord, startRow);

        RowRecord row = getRow(nextRowIx);
        if (row == null) {
            row = createRow(nextRowIx);
            insertRow(row);
        }
        // Write collapse field
        row.setColapsed(true);
    }

    /**
     * Create a row record.
     *
     * @param rowNumber row number
     * @return RowRecord created for the passed in row number
     * @see org.apache.poi.hssf.record.RowRecord
     */
    public static RowRecord createRow(int rowNumber) {
        return new RowRecord(rowNumber);
    }

    public boolean isRowGroupCollapsed(int row) {
        int collapseRow = findEndOfRowOutlineGroup(row) + 1;

        return getRow(collapseRow) != null && getRow(collapseRow).getColapsed();
    }

    public void expandRow(int rowNumber) {
        if (rowNumber == -1)
            return;

        // If it is already expanded do nothing.
        if (!isRowGroupCollapsed(rowNumber)) {
            return;
        }

        // Find the start of the group.
        int startIdx = findStartOfRowOutlineGroup(rowNumber);
        RowRecord row = getRow(startIdx);

        // Find the end of the group.
        int endIdx = findEndOfRowOutlineGroup(rowNumber);

        // expand:
        // collapsed bit must be unset
        // hidden bit gets unset _if_ surrounding groups are expanded you can determine
        //   this by looking at the hidden bit of the enclosing group.  You will have
        //   to look at the start and the end of the current group to determine which
        //   is the enclosing group
        // hidden bit only is altered for this outline level.  ie.  don't un-collapse contained groups
        if (!isRowGroupHiddenByParent(rowNumber)) {
            for (int i = startIdx; i <= endIdx; i++) {
                RowRecord otherRow = getRow(i);
                if (row.getOutlineLevel() == otherRow.getOutlineLevel() || !isRowGroupCollapsed(i)) {
                    otherRow.setZeroHeight(false);
                }
            }
        }

        // Write collapse field
        getRow(endIdx + 1).setColapsed(false);
    }

    public boolean isRowGroupHiddenByParent(int row) {
        // Look out outline details of end
        int endLevel;
        boolean endHidden;
        int endOfOutlineGroupIdx = findEndOfRowOutlineGroup(row);
        if (getRow(endOfOutlineGroupIdx + 1) == null) {
            endLevel = 0;
            endHidden = false;
        } else {
            endLevel = getRow(endOfOutlineGroupIdx + 1).getOutlineLevel();
            endHidden = getRow(endOfOutlineGroupIdx + 1).getZeroHeight();
        }

        // Look out outline details of start
        int startLevel;
        boolean startHidden;
        int startOfOutlineGroupIdx = findStartOfRowOutlineGroup( row );
        if (startOfOutlineGroupIdx - 1 < 0 || getRow(startOfOutlineGroupIdx - 1) == null) {
            startLevel = 0;
            startHidden = false;
        } else {
            startLevel = getRow(startOfOutlineGroupIdx - 1).getOutlineLevel();
            startHidden = getRow(startOfOutlineGroupIdx - 1).getZeroHeight();
        }

        if (endLevel > startLevel) {
            return endHidden;
        }

        return startHidden;
    }
    
    /**
     * Returns an iterator for the cell values
     */
    public Iterator<CellValueRecordInterface> getCellValueIterator() {
        return _valuesAgg.iterator();
    }

    public IndexRecord createIndexRecord(int indexRecordOffset, int sizeOfInitialSheetRecords) {
        IndexRecord result = new IndexRecord();
        result.setFirstRow(_firstrow);
        result.setLastRowAdd1(_lastrow + 1);
        // Calculate the size of the records from the end of the BOF
        // and up to the RowRecordsAggregate...

        // Add the references to the DBCells in the IndexRecord (one for each block)
        // Note: The offsets are relative to the Workbook BOF. Assume that this is
        // 0 for now.....

        int blockCount = getRowBlockCount();
        // Calculate the size of this IndexRecord
        int indexRecSize = IndexRecord.getRecordSizeForBlockCount(blockCount);

        int currentOffset = indexRecordOffset + indexRecSize + sizeOfInitialSheetRecords;

        for (int block = 0; block < blockCount; block++) {
            // each row-block has a DBCELL record.
            // The offset of each DBCELL record needs to be updated in the INDEX record

            // account for row records in this row-block
            currentOffset += getRowBlockSize(block);
            // account for cell value records after those
            currentOffset += _valuesAgg.getRowCellBlockSize(
                    getStartRowNumberForBlock(block), getEndRowNumberForBlock(block));

            // currentOffset is now the location of the DBCELL record for this row-block
            result.addDbcell(currentOffset);
            // Add space required to write the DBCELL record (whose reference was just added).
            currentOffset += (8 + (getRowCountForBlock(block) * 2));
        }
        return result;
    }
    public void insertCell(CellValueRecordInterface cvRec) {
        _valuesAgg.insertCell(cvRec);
    }
    public void removeCell(CellValueRecordInterface cvRec) {
        if (cvRec instanceof FormulaRecordAggregate) {
            ((FormulaRecordAggregate)cvRec).notifyFormulaChanging();
        }
        _valuesAgg.removeCell(cvRec);
    }
    public FormulaRecordAggregate createFormula(int row, int col) {
        FormulaRecord fr = new FormulaRecord();
        fr.setRow(row);
        fr.setColumn((short) col);
        return new FormulaRecordAggregate(fr, null, _sharedValueManager);
    }
    public void updateFormulasAfterRowShift(FormulaShifter formulaShifter, int currentExternSheetIndex) {
        _valuesAgg.updateFormulasAfterRowShift(formulaShifter, currentExternSheetIndex);
    }
    public DimensionsRecord createDimensions() {
        DimensionsRecord result = new DimensionsRecord();
        result.setFirstRow(_firstrow);
        result.setLastRow(_lastrow);
        result.setFirstCol((short) _valuesAgg.getFirstCellNum());
        result.setLastCol((short) _valuesAgg.getLastCellNum());
        return result;
    }
}
