/* ====================================================================
   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.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.poi.hssf.record.ArrayRecord;
import org.apache.poi.hssf.record.FormulaRecord;
import org.apache.poi.hssf.record.SharedFormulaRecord;
import org.apache.poi.hssf.record.SharedValueRecordBase;
import org.apache.poi.hssf.record.TableRecord;
import org.apache.poi.ss.formula.ptg.ExpPtg;
import org.apache.poi.hssf.util.CellRangeAddress8Bit;
import org.apache.poi.ss.util.CellReference;

/**
 * Manages various auxiliary records while constructing a
 * {@link RowRecordsAggregate}:
 * <ul>
 * <li>{@link SharedFormulaRecord}s</li>
 * <li>{@link ArrayRecord}s</li>
 * <li>{@link TableRecord}s</li>
 * </ul>
 *
 * @author Josh Micich
 * @author Vladimirs Abramovs(Vladimirs.Abramovs at exigenservices.com) - handling of ArrayRecords
 */
public final class SharedValueManager {

	private static final class SharedFormulaGroup {
		private final SharedFormulaRecord _sfr;
		private final FormulaRecordAggregate[] _frAggs;
		private int _numberOfFormulas;
		/**
		 * Coordinates of the first cell having a formula that uses this shared formula.
		 * This is often <i>but not always</i> the top left cell in the range covered by
		 * {@link #_sfr}
		 */
		private final CellReference _firstCell;

		public SharedFormulaGroup(SharedFormulaRecord sfr, CellReference firstCell) {
			if (!sfr.isInRange(firstCell.getRow(), firstCell.getCol())) {
				throw new IllegalArgumentException("First formula cell " + firstCell.formatAsString()
						+ " is not shared formula range " + sfr.getRange().toString() + ".");
			}
			_sfr = sfr;
			_firstCell = firstCell;
			int width = sfr.getLastColumn() - sfr.getFirstColumn() + 1;
			int height = sfr.getLastRow() - sfr.getFirstRow() + 1;
			_frAggs = new FormulaRecordAggregate[width * height];
			_numberOfFormulas = 0;
		}

		public void add(FormulaRecordAggregate agg) {
			if (_numberOfFormulas == 0) {
				if (_firstCell.getRow() != agg.getRow() || _firstCell.getCol() != agg.getColumn()) {
					throw new IllegalStateException("shared formula coding error: "+_firstCell.getCol()+'/'+_firstCell.getRow()+" != "+agg.getColumn()+'/'+agg.getRow());
				}
			}
			if (_numberOfFormulas >= _frAggs.length) {
				throw new RuntimeException("Too many formula records for shared formula group");
			}
			_frAggs[_numberOfFormulas++] = agg;
		}

		public void unlinkSharedFormulas() {
			for (int i = 0; i < _numberOfFormulas; i++) {
				_frAggs[i].unlinkSharedFormula();
			}
		}

		public SharedFormulaRecord getSFR() {
			return _sfr;
		}

		public final String toString() {
			StringBuffer sb = new StringBuffer(64);
			sb.append(getClass().getName()).append(" [");
			sb.append(_sfr.getRange().toString());
			sb.append("]");
			return sb.toString();
		}
	}

	/**
	 * @return a new empty {@link SharedValueManager}.
	 */
	public static SharedValueManager createEmpty() {
		// Note - must create distinct instances because they are assumed to be mutable.
		return new SharedValueManager(
			new SharedFormulaRecord[0], new CellReference[0], new ArrayRecord[0], new TableRecord[0]);
	}
	private final List<ArrayRecord> _arrayRecords;
	private final TableRecord[] _tableRecords;
	private final Map<SharedFormulaRecord, SharedFormulaGroup> _groupsBySharedFormulaRecord;
	/** cached for optimization purposes */
    private Map<Integer,SharedFormulaGroup> _groupsCache;

	private SharedValueManager(SharedFormulaRecord[] sharedFormulaRecords,
			CellReference[] firstCells, ArrayRecord[] arrayRecords, TableRecord[] tableRecords) {
		int nShF = sharedFormulaRecords.length;
		if (nShF != firstCells.length) {
			throw new IllegalArgumentException("array sizes don't match: " + nShF + "!=" + firstCells.length + ".");
		}
		_arrayRecords = toList(arrayRecords);
		_tableRecords = tableRecords;
		Map<SharedFormulaRecord, SharedFormulaGroup> m = new HashMap<SharedFormulaRecord, SharedFormulaGroup>(nShF * 3 / 2);
		for (int i = 0; i < nShF; i++) {
			SharedFormulaRecord sfr = sharedFormulaRecords[i];
			m.put(sfr, new SharedFormulaGroup(sfr, firstCells[i]));
		}
		_groupsBySharedFormulaRecord = m;
	}

	/**
	 * @return a modifiable list, independent of the supplied array
	 */
	private static <Z> List<Z> toList(Z[] zz) {
		List<Z> result = new ArrayList<Z>(zz.length);
		for (int i = 0; i < zz.length; i++) {
			result.add(zz[i]);
		}
		return result;
	}

	/**
	 */
	public static SharedValueManager create(SharedFormulaRecord[] sharedFormulaRecords,
			CellReference[] firstCells, ArrayRecord[] arrayRecords, TableRecord[] tableRecords) {
		if (sharedFormulaRecords.length + firstCells.length + arrayRecords.length + tableRecords.length < 1) {
			return createEmpty();
		}
		return new SharedValueManager(sharedFormulaRecords, firstCells, arrayRecords, tableRecords);
	}


	/**
	 * @param firstCell as extracted from the {@link ExpPtg} from the cell's formula.
	 * @return never <code>null</code>
	 */
	public SharedFormulaRecord linkSharedFormulaRecord(CellReference firstCell, FormulaRecordAggregate agg) {
		SharedFormulaGroup result = findFormulaGroupForCell(firstCell);
        if(null == result) {
            throw new RuntimeException("Failed to find a matching shared formula record");
        }
		result.add(agg);
		return result.getSFR();
	}

    private SharedFormulaGroup findFormulaGroupForCell(final CellReference cellRef) {
        if(null == _groupsCache) {
            _groupsCache = new HashMap<Integer,SharedFormulaGroup>(_groupsBySharedFormulaRecord.size());
            for(SharedFormulaGroup group: _groupsBySharedFormulaRecord.values()) {
                _groupsCache.put(getKeyForCache(group._firstCell),group);
            }
        }
        SharedFormulaGroup sfg = _groupsCache.get(getKeyForCache(cellRef));
        return sfg;
    }

    private Integer getKeyForCache(final CellReference cellRef) {
        // The HSSF has a max of 2^16 rows and 2^8 cols
        return ((cellRef.getCol()+1)<<16 | cellRef.getRow());
    }

	/**
	 * Gets the {@link SharedValueRecordBase} record if it should be encoded immediately after the
	 * formula record contained in the specified {@link FormulaRecordAggregate} agg.  Note - the
	 * shared value record always appears after the first formula record in the group.  For arrays
	 * and tables the first formula is always the in the top left cell.  However, since shared
	 * formula groups can be sparse and/or overlap, the first formula may not actually be in the
	 * top left cell.
	 *
	 * @return the SHRFMLA, TABLE or ARRAY record for the formula cell, if it is the first cell of
	 * a table or array region. <code>null</code> if the formula cell is not shared/array/table,
	 * or if the specified formula is not the the first in the group.
	 */
	public SharedValueRecordBase getRecordForFirstCell(FormulaRecordAggregate agg) {
		CellReference firstCell = agg.getFormulaRecord().getFormula().getExpReference();
		// perhaps this could be optimised by consulting the (somewhat unreliable) isShared flag
		// and/or distinguishing between tExp and tTbl.
		if (firstCell == null) {
			// not a shared/array/table formula
			return null;
		}


		int row = firstCell.getRow();
		int column = firstCell.getCol();
		if (agg.getRow() != row || agg.getColumn() != column) {
			// not the first formula cell in the group
			return null;
		}

        if(!_groupsBySharedFormulaRecord.isEmpty()) {
            SharedFormulaGroup sfg = findFormulaGroupForCell(firstCell);
            if(null != sfg) {
                return sfg.getSFR();
            }
        }

		// Since arrays and tables cannot be sparse (all cells in range participate)
		// The first cell will be the top left in the range.  So we can match the
		// ARRAY/TABLE record directly.

		for (TableRecord tr : _tableRecords) {
			if (tr.isFirstCell(row, column)) {
				return tr;
			}
		}
		for (ArrayRecord ar : _arrayRecords) {
			if (ar.isFirstCell(row, column)) {
				return ar;
			}
		}
		return null;
	}

	/**
	 * Converts all {@link FormulaRecord}s handled by <tt>sharedFormulaRecord</tt>
	 * to plain unshared formulas
	 */
	public void unlink(SharedFormulaRecord sharedFormulaRecord) {
		SharedFormulaGroup svg = _groupsBySharedFormulaRecord.remove(sharedFormulaRecord);
		if (svg == null) {
			throw new IllegalStateException("Failed to find formulas for shared formula");
		}
		_groupsCache = null; // be sure to reset cached value
		svg.unlinkSharedFormulas();
	}

	/**
	 * Add specified Array Record.
	 */
	public void addArrayRecord(ArrayRecord ar) {
		// could do a check here to make sure none of the ranges overlap
		_arrayRecords.add(ar);
	}

	/**
	 * Removes the {@link ArrayRecord} for the cell group containing the specified cell.
	 * The caller should clear (set blank) all cells in the returned range.
	 * @return the range of the array formula which was just removed. Never <code>null</code>.
	 */
	public CellRangeAddress8Bit removeArrayFormula(int rowIndex, int columnIndex) {
		for (ArrayRecord ar : _arrayRecords) {
			if (ar.isInRange(rowIndex, columnIndex)) {
				_arrayRecords.remove(ar);
				return ar.getRange();
			}
		}
		String ref = new CellReference(rowIndex, columnIndex, false, false).formatAsString();
		throw new IllegalArgumentException("Specified cell " + ref
				+ " is not part of an array formula.");
	}

	/**
	 * @return the shared ArrayRecord identified by (firstRow, firstColumn). never <code>null</code>.
	 */
	public ArrayRecord getArrayRecord(int firstRow, int firstColumn) {
		for(ArrayRecord ar : _arrayRecords) {
			if(ar.isFirstCell(firstRow, firstColumn)) {
				return ar;
			}
		}
		return null;
	}
}
