/* ====================================================================
   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;
	}
}
