/* ====================================================================
   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.Iterator;
import java.util.NoSuchElementException;

import org.apache.poi.hssf.model.RecordStream;
import org.apache.poi.hssf.record.BlankRecord;
import org.apache.poi.hssf.record.CellValueRecordInterface;
import org.apache.poi.hssf.record.FormulaRecord;
import org.apache.poi.hssf.record.MulBlankRecord;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.RecordBase;
import org.apache.poi.hssf.record.StringRecord;
import org.apache.poi.hssf.record.aggregates.RecordAggregate.RecordVisitor;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.formula.FormulaShifter;
import org.apache.poi.ss.formula.ptg.Ptg;
import org.apache.poi.util.Removal;

/**
 *
 * Aggregate value records together.  Things are easier to handle that way.
 *
 * @author  andy
 * @author  Glen Stampoultzis (glens at apache.org)
 * @author Jason Height (jheight at chariot dot net dot au)
 */
public final class ValueRecordsAggregate implements Iterable<CellValueRecordInterface> {
	private static final int MAX_ROW_INDEX = 0XFFFF;
	private static final int INDEX_NOT_SET = -1;
	private int firstcell = INDEX_NOT_SET;
	private int lastcell  = INDEX_NOT_SET;
	private CellValueRecordInterface[][] records;

	/** Creates a new instance of ValueRecordsAggregate */

	public ValueRecordsAggregate() {
		this(INDEX_NOT_SET, INDEX_NOT_SET, new CellValueRecordInterface[30][]); // We start with 30 Rows.
	}
	private ValueRecordsAggregate(int firstCellIx, int lastCellIx, CellValueRecordInterface[][] pRecords) {
		firstcell = firstCellIx;
		lastcell = lastCellIx;
		records = pRecords;
	}

	public void insertCell(CellValueRecordInterface cell) {
		short column = cell.getColumn();
		int row = cell.getRow();
		if (row >= records.length) {
			CellValueRecordInterface[][] oldRecords = records;
			int newSize = oldRecords.length * 2;
			if (newSize < row + 1)
				newSize = row + 1;
			records = new CellValueRecordInterface[newSize][];
			System.arraycopy(oldRecords, 0, records, 0, oldRecords.length);
		}
		CellValueRecordInterface[] rowCells = records[row];
		if (rowCells == null) {
			int newSize = column + 1;
			if (newSize < 10)
				newSize = 10;
			rowCells = new CellValueRecordInterface[newSize];
			records[row] = rowCells;
		}
		if (column >= rowCells.length) {
			CellValueRecordInterface[] oldRowCells = rowCells;
			int newSize = oldRowCells.length * 2;
			if (newSize < column + 1)
				newSize = column + 1;
			// if(newSize>257) newSize=257; // activate?
			rowCells = new CellValueRecordInterface[newSize];
			System.arraycopy(oldRowCells, 0, rowCells, 0, oldRowCells.length);
			records[row] = rowCells;
		}
		rowCells[column] = cell;

		if (column < firstcell || firstcell == INDEX_NOT_SET) {
			firstcell = column;
		}
		if (column > lastcell || lastcell == INDEX_NOT_SET) {
			lastcell = column;
		}
	}

	public void removeCell(CellValueRecordInterface cell) {
		if (cell == null) {
			throw new IllegalArgumentException("cell must not be null");
		}
		int row = cell.getRow();
		if (row >= records.length) {
			throw new RuntimeException("cell row is out of range");
		}
		CellValueRecordInterface[] rowCells = records[row];
		if (rowCells == null) {
			throw new RuntimeException("cell row is already empty");
		}
		short column = cell.getColumn();
		if (column >= rowCells.length) {
			throw new RuntimeException("cell column is out of range");
		}
		rowCells[column] = null;
	}

	public void removeAllCellsValuesForRow(int rowIndex) {
		if (rowIndex < 0 || rowIndex > MAX_ROW_INDEX) {
			throw new IllegalArgumentException("Specified rowIndex " + rowIndex
					+ " is outside the allowable range (0.." +MAX_ROW_INDEX + ")");
		}
		if (rowIndex >= records.length) {
			// this can happen when the client code has created a row,
			// and then removes/replaces it before adding any cells. (see bug 46312)
			return;
		}

		records[rowIndex] = null;
	}


	public int getPhysicalNumberOfCells() {
		int count = 0;
		for (int r = 0; r < records.length; r++) {
			CellValueRecordInterface[] rowCells = records[r];
			if (rowCells != null) {
				for (int c = 0; c < rowCells.length; c++) {
					if (rowCells[c] != null)
						count++;
				}
			}
		}
		return count;
	}

	public int getFirstCellNum() {
		return firstcell;
	}

	public int getLastCellNum() {
		return lastcell;
	}

	public void addMultipleBlanks(MulBlankRecord mbr) {
		for (int j = 0; j < mbr.getNumColumns(); j++) {
			BlankRecord br = new BlankRecord();

			br.setColumn(( short ) (j + mbr.getFirstColumn()));
			br.setRow(mbr.getRow());
			br.setXFIndex(mbr.getXFAt(j));
			insertCell(br);
		}
	}

	/**
	 * Processes a single cell value record
	 * @param sfh used to resolve any shared-formulas/arrays/tables for the current sheet
	 */
	public void construct(CellValueRecordInterface rec, RecordStream rs, SharedValueManager sfh) {
		if (rec instanceof FormulaRecord) {
			FormulaRecord formulaRec = (FormulaRecord)rec;
			// read optional cached text value
			StringRecord cachedText;
			Class<? extends Record> nextClass = rs.peekNextClass();
			if (nextClass == StringRecord.class) {
				cachedText = (StringRecord) rs.getNext();
			} else {
				cachedText = null;
			}
			insertCell(new FormulaRecordAggregate(formulaRec, cachedText, sfh));
		} else {
			insertCell(rec);
		}
	}

	/** Tallies a count of the size of the cell records
	 *  that are attached to the rows in the range specified.
	 */
	public int getRowCellBlockSize(int startRow, int endRow) {
		int result = 0;
		for(int rowIx=startRow; rowIx<=endRow && rowIx<records.length; rowIx++) {
			result += getRowSerializedSize(records[rowIx]);
		}
		return result;
	}

	/** Returns true if the row has cells attached to it */
	public boolean rowHasCells(int row) {
		if (row >= records.length) {
			return false;
		}
		CellValueRecordInterface[] rowCells=records[row];
		if(rowCells==null) return false;
		for(int col=0;col<rowCells.length;col++) {
			if(rowCells[col]!=null) return true;
		}
		return false;
	}

	private static int getRowSerializedSize(CellValueRecordInterface[] rowCells) {
		if(rowCells == null) {
			return 0;
		}
		int result = 0;
		for (int i = 0; i < rowCells.length; i++) {
			RecordBase cvr = (RecordBase) rowCells[i];
			if(cvr == null) {
				continue;
			}
			int nBlank = countBlanks(rowCells, i);
			if (nBlank > 1) {
				result += (10 + 2*nBlank);
				i+=nBlank-1;
			} else {
				result += cvr.getRecordSize();
			}
		}
		return result;
	}

	public void visitCellsForRow(int rowIndex, RecordVisitor rv) {

		CellValueRecordInterface[] rowCells = records[rowIndex];
		if(rowCells == null) {
			throw new IllegalArgumentException("Row [" + rowIndex + "] is empty");
		}


		for (int i = 0; i < rowCells.length; i++) {
			RecordBase cvr = (RecordBase) rowCells[i];
			if(cvr == null) {
				continue;
			}
			int nBlank = countBlanks(rowCells, i);
			if (nBlank > 1) {
				rv.visitRecord(createMBR(rowCells, i, nBlank));
				i+=nBlank-1;
			} else if (cvr instanceof RecordAggregate) {
				RecordAggregate agg = (RecordAggregate) cvr;
				agg.visitContainedRecords(rv);
			} else {
				rv.visitRecord((org.apache.poi.hssf.record.Record) cvr);
			}
		}
	}

	/**
	 * @return the number of <em>consecutive</em> {@link BlankRecord}s in the specified row
	 * starting from startIx.
	 */
	private static int countBlanks(CellValueRecordInterface[] rowCellValues, int startIx) {
		int i = startIx;
		while(i < rowCellValues.length) {
			CellValueRecordInterface cvr = rowCellValues[i];
			if (!(cvr instanceof BlankRecord)) {
				break;
			}
			i++;
		}
		return i - startIx;
	}

	private MulBlankRecord createMBR(CellValueRecordInterface[] cellValues, int startIx, int nBlank) {

		short[] xfs = new short[nBlank];
		for (int i = 0; i < xfs.length; i++) {
			xfs[i] = cellValues[startIx + i].getXFIndex();
		}
		int rowIx = cellValues[startIx].getRow();
		return new MulBlankRecord(rowIx, startIx, xfs);
	}

	public void updateFormulasAfterRowShift(FormulaShifter shifter, int currentExternSheetIndex) {
		for (int i = 0; i < records.length; i++) {
			CellValueRecordInterface[] rowCells = records[i];
			if (rowCells == null) {
				continue;
			}
			for (int j = 0; j < rowCells.length; j++) {
				CellValueRecordInterface cell = rowCells[j];
				if (cell instanceof FormulaRecordAggregate) {
                    FormulaRecordAggregate fra = (FormulaRecordAggregate)cell;
                    Ptg[] ptgs = fra.getFormulaTokens(); // needs clone() inside this getter?
                    Ptg[] ptgs2 = ((FormulaRecordAggregate)cell).getFormulaRecord().getParsedExpression(); // needs clone() inside this getter?

                    if (shifter.adjustFormula(ptgs, currentExternSheetIndex)) {
                        fra.setParsedExpression(ptgs);
                    }
                }
			}
		}
	}

	/**
	 * iterator for CellValueRecordInterface
	 */
	class ValueIterator implements Iterator<CellValueRecordInterface> {

		int curRowIndex, curColIndex = -1;
		int nextRowIndex, nextColIndex = -1;

		public ValueIterator() {
			getNextPos();
		}

		void getNextPos() {
			if (nextRowIndex >= records.length)
				return; // no next already

			while (nextRowIndex < records.length) {
				++nextColIndex;
				if (records[nextRowIndex] == null || nextColIndex >= records[nextRowIndex].length) {
					++nextRowIndex;
					nextColIndex = -1;
					continue;
				}

				if (records[nextRowIndex][nextColIndex] != null)
					return; // next cell found
			}
			// no next found
		}

		public boolean hasNext() {
			return nextRowIndex < records.length;
		}

		public CellValueRecordInterface next() {
			if (!hasNext()) {
				throw new NoSuchElementException();
			}

			curRowIndex = nextRowIndex;
			curColIndex = nextColIndex;
			final CellValueRecordInterface ret = records[curRowIndex][curColIndex];
			getNextPos();
			return ret;
		}

		public void remove() {
			records[curRowIndex][curColIndex] = null;
		}
	}

	/** value iterator */
	public Iterator<CellValueRecordInterface> iterator() {
		return new ValueIterator();
	}

	/**
	 * @deprecated use {@link org.apache.poi.hssf.usermodel.HSSFSheet#cloneSheet(HSSFWorkbook)} instead
	 */
	@Override
	@SuppressWarnings("squid:S2975")
	@Deprecated
	@Removal(version = "5.0.0")
	public Object clone() {
		throw new RuntimeException("clone() should not be called.  ValueRecordsAggregate should be copied via Sheet.cloneSheet()");
	}
}
