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

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

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.message.SimpleMessage;
import org.apache.poi.hssf.record.*;
import org.apache.poi.hssf.record.Record;
import org.apache.poi.hssf.record.aggregates.ChartSubstreamRecordAggregate;
import org.apache.poi.hssf.record.aggregates.ColumnInfoRecordsAggregate;
import org.apache.poi.hssf.record.aggregates.ConditionalFormattingTable;
import org.apache.poi.hssf.record.aggregates.CustomViewSettingsRecordAggregate;
import org.apache.poi.hssf.record.aggregates.DataValidityTable;
import org.apache.poi.hssf.record.aggregates.MergedCellsTable;
import org.apache.poi.hssf.record.aggregates.PageSettingsBlock;
import org.apache.poi.hssf.record.aggregates.RecordAggregate;
import org.apache.poi.hssf.record.aggregates.RecordAggregate.PositionTrackingVisitor;
import org.apache.poi.hssf.record.aggregates.RecordAggregate.RecordVisitor;
import org.apache.poi.hssf.record.aggregates.RowRecordsAggregate;
import org.apache.poi.hssf.record.aggregates.WorksheetProtectionBlock;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.ss.formula.FormulaShifter;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.PaneInformation;
import org.apache.poi.util.Internal;
import org.apache.poi.util.RecordFormatException;

import static org.apache.logging.log4j.util.Unbox.box;

/**
 * Low level model implementation of a Sheet (one workbook contains many sheets)
 * This file contains the low level binary records starting at the sheets BOF and
 * ending with the sheets EOF.  Use HSSFSheet for a high level representation.
 * <P>
 * The structures of the highlevel API use references to this to perform most of their
 * operations.  Its probably unwise to use these low level structures directly unless you
 * really know what you're doing.  I recommend you read the Microsoft Excel 97 Developer's
 * Kit (Microsoft Press) and the documentation at http://sc.openoffice.org/excelfileformat.pdf
 * before even attempting to use this.
 *
 * @see InternalWorkbook
 * @see HSSFSheet
 */
@Internal
public final class InternalSheet {
    public static final short   LeftMargin = 0;
    public static final short   RightMargin = 1;
    public static final short   TopMargin = 2;
    public static final short   BottomMargin = 3;

    private static final Logger LOGGER = LogManager.getLogger(InternalSheet.class);

    private List<RecordBase>             _records;
    protected PrintGridlinesRecord       printGridlines;
    protected PrintHeadersRecord         printHeaders;
    protected GridsetRecord              gridset;
    private   GutsRecord                 _gutsRecord;
    protected DefaultColWidthRecord      defaultcolwidth   =     new DefaultColWidthRecord();
    protected DefaultRowHeightRecord     defaultrowheight  =     new DefaultRowHeightRecord();
    private PageSettingsBlock _psBlock;

    /**
     * 'Worksheet Protection Block'<br>
     *  Aggregate object is always present, but possibly empty.
     */
    private final WorksheetProtectionBlock _protectionBlock = new WorksheetProtectionBlock();

    protected WindowTwoRecord            windowTwo;
    protected SelectionRecord            _selection;
    /** java object always present, but if empty no BIFF records are written */
    private final MergedCellsTable       _mergedCellsTable;
    /** always present in this POI object, not always written to Excel file */
    /*package*/ColumnInfoRecordsAggregate _columnInfos;
    /** the DimensionsRecord is always present */
    private DimensionsRecord             _dimensions;
    /** always present */
    protected final RowRecordsAggregate  _rowsAggregate;
    private   DataValidityTable          _dataValidityTable;
    private   ConditionalFormattingTable condFormatting;

    private   Iterator<RowRecord>        rowRecIterator;

    /** Add an UncalcedRecord if not true indicating formulas have not been calculated */
    protected boolean _isUncalced;

    public static final byte PANE_LOWER_RIGHT = (byte)0;
    public static final byte PANE_UPPER_RIGHT = (byte)1;
    public static final byte PANE_LOWER_LEFT = (byte)2;
    public static final byte PANE_UPPER_LEFT = (byte)3;

    /**
     * read support  (offset used as starting point for search) for low level
     * API.  Pass in an array of Record objects, the sheet number (0 based) and
     * a record offset (should be the location of the sheets BOF record).  A Sheet
     * object is constructed and passed back with all of its initialization set
     * to the passed in records and references to those records held. This function
     * is normally called via Workbook.
     *
     * @param rs the stream to read records from
     *
     * @return Sheet object with all values set to those read from the file
     *
     * @see InternalWorkbook
     * @see Record
     */
    public static InternalSheet createSheet(RecordStream rs) {
        return new InternalSheet(rs);
    }
    private InternalSheet(RecordStream rs) {
        _mergedCellsTable = new MergedCellsTable();
        RowRecordsAggregate rra = null;

        List<RecordBase> records = new ArrayList<>(128);
        _records = records; // needed here due to calls to findFirstRecordLocBySid before we're done
        int dimsloc = -1;

        if (rs.peekNextSid() != BOFRecord.sid) {
            throw new RecordFormatException("BOF record expected");
        }

        BOFRecord bof = (BOFRecord) rs.getNext();
        if (bof.getType() == BOFRecord.TYPE_WORKSHEET) {
            // Good, well supported
        } else if (bof.getType() == BOFRecord.TYPE_CHART ||
                   bof.getType() == BOFRecord.TYPE_EXCEL_4_MACRO) {
            // These aren't really typical sheets... Let it go though,
            //  we can handle them roughly well enough as a "normal" one
        } else {
            // Not a supported type
            // Skip onto the EOF, then complain
            while (rs.hasNext()) {
                Record rec = rs.getNext();
                if (rec instanceof EOFRecord) {
                    break;
                }
            }
            throw new UnsupportedBOFType(bof.getType());
        }
        records.add(bof);

        while (rs.hasNext()) {
            int recSid = rs.peekNextSid();

            if ( recSid == CFHeaderRecord.sid || recSid == CFHeader12Record.sid ) {
                condFormatting = new ConditionalFormattingTable(rs);
                records.add(condFormatting);
                continue;
            }

            if (recSid == ColumnInfoRecord.sid) {
                _columnInfos = new ColumnInfoRecordsAggregate(rs);
                records.add(_columnInfos);
                continue;
            }
            if ( recSid == DVALRecord.sid) {
                _dataValidityTable = new DataValidityTable(rs);
                records.add(_dataValidityTable);
                continue;
            }

            if (RecordOrderer.isRowBlockRecord(recSid)) {
                //only add the aggregate once
                if (rra != null) {
                    throw new RecordFormatException("row/cell records found in the wrong place");
                }
                RowBlocksReader rbr = new RowBlocksReader(rs);
                _mergedCellsTable.addRecords(rbr.getLooseMergedCells());
                rra = new RowRecordsAggregate(rbr.getPlainRecordStream(), rbr.getSharedFormulaManager());
                records.add(rra); //only add the aggregate once
                continue;
            }

            if (CustomViewSettingsRecordAggregate.isBeginRecord(recSid)) {
                // This happens three times in test sample file "29982.xls"
                // Also several times in bugzilla samples 46840-23373 and 46840-23374
                records.add(new CustomViewSettingsRecordAggregate(rs));
                continue;
            }

            if (PageSettingsBlock.isComponentRecord(recSid)) {
                if (_psBlock == null) {
                    // first PSB record encountered - read all of them:
                    _psBlock = new PageSettingsBlock(rs);
                    records.add(_psBlock);
                } else {
                    // one or more PSB records found after some intervening non-PSB records
                    _psBlock.addLateRecords(rs);
                }
                // YK: in some cases records can be moved to the preceding
                // CustomViewSettingsRecordAggregate blocks
                _psBlock.positionRecords(records);
                continue;
            }

            if (WorksheetProtectionBlock.isComponentRecord(recSid)) {
                _protectionBlock.addRecords(rs);
                continue;
            }

            if (recSid == MergeCellsRecord.sid) {
                // when the MergedCellsTable is found in the right place, we expect those records to be contiguous
                _mergedCellsTable.read(rs);
                continue;
            }

            if (recSid == BOFRecord.sid) {
                ChartSubstreamRecordAggregate chartAgg = new ChartSubstreamRecordAggregate(rs);
//                if (false) {
//                    // TODO - would like to keep the chart aggregate packed, but one unit test needs attention
//                    records.add(chartAgg);
//                } else {
                    spillAggregate(chartAgg, records);
//                }
                continue;
            }

            Record rec = rs.getNext();
            if ( recSid == IndexRecord.sid ) {
                // ignore INDEX record because it is only needed by Excel,
                // and POI always re-calculates its contents
                continue;
            }


            if (recSid == UncalcedRecord.sid) {
                // don't add UncalcedRecord to the list
                _isUncalced = true; // this flag is enough
                continue;
            }

            if (recSid == FeatRecord.sid ||
            		recSid == FeatHdrRecord.sid) {
                records.add(rec);
                continue;
            }

            if (recSid == EOFRecord.sid) {
                records.add(rec);
                break;
            }

            if (recSid == DimensionsRecord.sid)
            {
                // Make a columns aggregate if one hasn't ready been created.
                if (_columnInfos == null)
                {
                    _columnInfos = new ColumnInfoRecordsAggregate();
                    records.add(_columnInfos);
                }

                _dimensions    = ( DimensionsRecord ) rec;
                dimsloc = records.size();
            }
            else if (recSid == DefaultColWidthRecord.sid)
            {
                defaultcolwidth = ( DefaultColWidthRecord ) rec;
            }
            else if (recSid == DefaultRowHeightRecord.sid)
            {
                defaultrowheight = ( DefaultRowHeightRecord ) rec;
            }
            else if ( recSid == PrintGridlinesRecord.sid )
            {
                printGridlines = (PrintGridlinesRecord) rec;
            }
            else if ( recSid == PrintHeadersRecord.sid )
            {
                printHeaders = (PrintHeadersRecord) rec;
            }
            else if ( recSid == GridsetRecord.sid )
            {
                gridset = (GridsetRecord) rec;
            }
            else if ( recSid == SelectionRecord.sid )
            {
                _selection = (SelectionRecord) rec;
            }
            else if ( recSid == WindowTwoRecord.sid )
            {
                windowTwo = (WindowTwoRecord) rec;
            }
            else if ( recSid == GutsRecord.sid )
            {
                _gutsRecord = (GutsRecord) rec;
            }

            records.add(rec);
        }
        if (windowTwo == null) {
            throw new RecordFormatException("WINDOW2 was not found");
        }
        if (_dimensions == null) {
            // Excel seems to always write the DIMENSION record, but tolerates when it is not present
            // in all cases Excel (2007) adds the missing DIMENSION record
            if (rra == null) {
                // bug 46206 alludes to files which skip the DIMENSION record
                // when there are no row/cell records.
                // Not clear which application wrote these files.
                rra = new RowRecordsAggregate();
            } else {
                LOGGER.atWarn().log("DIMENSION record not found even though row/cells present");
                // Not sure if any tools write files like this, but Excel reads them OK
            }
            dimsloc = findFirstRecordLocBySid(WindowTwoRecord.sid);
            _dimensions = rra.createDimensions();
            records.add(dimsloc, _dimensions);
        }
        if (rra == null) {
            rra = new RowRecordsAggregate();
            records.add(dimsloc + 1, rra);
        }
        _rowsAggregate = rra;
        // put merged cells table in the right place (regardless of where the first MergedCellsRecord was found */
        RecordOrderer.addNewSheetRecord(records, _mergedCellsTable);
        RecordOrderer.addNewSheetRecord(records, _protectionBlock);
        LOGGER.atDebug().log("sheet createSheet (existing file) exited");
    }
    private static void spillAggregate(RecordAggregate ra, final List<RecordBase> recs) {
        ra.visitContainedRecords(r -> recs.add(r));
    }

    public static class UnsupportedBOFType extends RecordFormatException {
        private final int type;
        protected UnsupportedBOFType(int type) {
            super("BOF not of a supported type, found " + type);
            this.type = type;
        }

        public int getType() {
            return type;
        }
    }

    private static final class RecordCloner implements RecordVisitor {

        private final List<Record> _destList;

        public RecordCloner(List<Record> destList) {
            _destList = destList;
        }
        public void visitRecord(Record r) {
            _destList.add(r.copy());
        }
    }

    /**
     * Clones the low level records of this sheet and returns the new sheet instance.
     * This method is implemented by adding methods for deep cloning to all records that
     * can be added to a sheet. The <b>Record</b> object does not implement cloneable.
     * When adding a new record, implement a public clone method if and only if the record
     * belongs to a sheet.
     *
     * @return the cloned sheet
     */
    public InternalSheet cloneSheet() {
        List<Record> clonedRecords = new ArrayList<>(_records.size());
        for (int i = 0; i < _records.size(); i++) {
            RecordBase rb = _records.get(i);
            if (rb instanceof RecordAggregate) {
                ((RecordAggregate) rb).visitContainedRecords(new RecordCloner(clonedRecords));
                continue;
            }
            if (rb instanceof EscherAggregate){
                /**
                 * this record will be removed after reading actual data from EscherAggregate
                 */
                rb = new DrawingRecord();
            }
            Record rec = ((Record) rb).copy();
            clonedRecords.add(rec);
        }
        return createSheet(new RecordStream(clonedRecords, 0));
    }

    /**
     * Creates a sheet with all the usual records minus values and the "index"
     * record (not required).  Sets the location pointer to where the first value
     * records should go.  Use this to create a sheet from "scratch".
     *
     * @return Sheet object with all values set to defaults
     */
    public static InternalSheet createSheet() {
        return new InternalSheet();
    }

    private InternalSheet() {
        _mergedCellsTable = new MergedCellsTable();
        List<RecordBase> records = new ArrayList<>(32);

        LOGGER.atDebug().log("Sheet createsheet from scratch called");

        records.add(createBOF());

        records.add(createCalcMode());
        records.add(createCalcCount() );
        records.add(createRefMode() );
        records.add(createIteration() );
        records.add(createDelta() );
        records.add(createSaveRecalc() );
        printHeaders = createPrintHeaders();
        records.add(printHeaders);
        printGridlines = createPrintGridlines();
        records.add( printGridlines );
        gridset = createGridset();
        records.add( gridset );
        _gutsRecord = createGuts();
        records.add( _gutsRecord );
        defaultrowheight = createDefaultRowHeight();
        records.add( defaultrowheight );
        records.add( createWSBool() );

        // 'Page Settings Block'
        _psBlock = new PageSettingsBlock();
        records.add(_psBlock);

        // 'Worksheet Protection Block' (after 'Page Settings Block' and before DEFCOLWIDTH)
        records.add(_protectionBlock); // initially empty

        defaultcolwidth = createDefaultColWidth();
        records.add( defaultcolwidth);
        ColumnInfoRecordsAggregate columns = new ColumnInfoRecordsAggregate();
        records.add( columns );
        _columnInfos = columns;
        _dimensions = createDimensions();
        records.add(_dimensions);
        _rowsAggregate = new RowRecordsAggregate();
        records.add(_rowsAggregate);
        // 'Sheet View Settings'
        records.add(windowTwo = createWindowTwo());
        _selection = createSelection();
        records.add(_selection);

        records.add(_mergedCellsTable); // MCT comes after 'Sheet View Settings'
        records.add(EOFRecord.instance);

        _records = records;
        LOGGER.atDebug().log("Sheet createsheet from scratch exit");
    }

    public RowRecordsAggregate getRowsAggregate() {
        return _rowsAggregate;
    }

    private MergedCellsTable getMergedRecords() {
        // always present
        return _mergedCellsTable;
    }

    /**
     * Updates formulas in cells and conditional formats due to moving of cells
     *
     * @param shifter the formular shifter
     * @param externSheetIndex the externSheet index of this sheet
     */
    public void updateFormulasAfterCellShift(FormulaShifter shifter, int externSheetIndex) {
        getRowsAggregate().updateFormulasAfterRowShift(shifter, externSheetIndex);
        if (condFormatting != null) {
            getConditionalFormattingTable().updateFormulasAfterCellShift(shifter, externSheetIndex);
        }
        // TODO - adjust data validations
    }

    public int addMergedRegion(int rowFrom, int colFrom, int rowTo, int colTo) {
        // Validate input
        if (rowTo < rowFrom) {
            throw new IllegalArgumentException("The 'to' row (" + rowTo
                    + ") must not be less than the 'from' row (" + rowFrom + ")");
        }
        if (colTo < colFrom) {
            throw new IllegalArgumentException("The 'to' col (" + colTo
                    + ") must not be less than the 'from' col (" + colFrom + ")");
        }

        MergedCellsTable mrt = getMergedRecords();
        mrt.addArea(rowFrom, colFrom, rowTo, colTo);
        return mrt.getNumberOfMergedRegions()-1;
    }

    public void removeMergedRegion(int index) {
        //safety checks
        MergedCellsTable mrt = getMergedRecords();
        if (index >= mrt.getNumberOfMergedRegions()) {
            return;
        }
        mrt.remove(index);
    }

    public CellRangeAddress getMergedRegionAt(int index) {
        //safety checks
        MergedCellsTable mrt = getMergedRecords();
        if (index >=  mrt.getNumberOfMergedRegions()) {
            return null;
        }
        return mrt.get(index);
    }

    public int getNumMergedRegions() {
        return getMergedRecords().getNumberOfMergedRegions();
    }
    public ConditionalFormattingTable getConditionalFormattingTable() {
        if (condFormatting == null) {
            condFormatting = new ConditionalFormattingTable();
            RecordOrderer.addNewSheetRecord(_records, condFormatting);
        }
        return condFormatting;
    }

    /**
     * Per an earlier reported bug in working with Andy Khan's excel read library.  This
     * sets the values in the sheet's DimensionsRecord object to be correct.  Excel doesn't
     * really care, but we want to play nice with other libraries.
     *
     * @param firstrow the first row index
     * @param firstcol the first column index
     * @param lastrow the last row index
     * @param lastcol the last column index
     *
     * @see DimensionsRecord
     */
    public void setDimensions(int firstrow, short firstcol, int lastrow, short lastcol)
    {
        LOGGER.atDebug().log("Sheet.setDimensions");
        LOGGER.atDebug().log(() -> new SimpleMessage(
                "firstrow" + firstrow +
                        "firstcol" + firstcol +
                        "lastrow" + lastrow +
                        "lastcol" + lastcol
        ));
        _dimensions.setFirstCol(firstcol);
        _dimensions.setFirstRow(firstrow);
        _dimensions.setLastCol(lastcol);
        _dimensions.setLastRow(lastrow);
        LOGGER.atDebug().log("Sheet.setDimensions exiting");
    }

    public void visitContainedRecords(RecordVisitor rv, int offset) {

        PositionTrackingVisitor ptv = new PositionTrackingVisitor(rv, offset);

        boolean haveSerializedIndex = false;

        for (int k = 0; k < _records.size(); k++) {
            RecordBase record = _records.get(k);

            if (record instanceof RecordAggregate) {
                RecordAggregate agg = (RecordAggregate) record;
                agg.visitContainedRecords(ptv);
            } else {
                ptv.visitRecord((Record) record);
            }

            // If the BOF record was just serialized then add the IndexRecord
            if (record instanceof BOFRecord) {
              if (!haveSerializedIndex) {
                haveSerializedIndex = true;
                // Add an optional UncalcedRecord. However, we should add
                //  it in only the once, after the sheet's own BOFRecord.
                // If there are diagrams, they have their own BOFRecords,
                //  and one shouldn't go in after that!
                if (_isUncalced) {
                    ptv.visitRecord(new UncalcedRecord());
                }
                //Can there be more than one BOF for a sheet? If not then we can
                //remove this guard. So be safe it is left here.
                if (_rowsAggregate != null) {
                    // find forward distance to first RowRecord
                    int initRecsSize = getSizeOfInitialSheetRecords(k);
                    int currentPos = ptv.getPosition();
                    ptv.visitRecord(_rowsAggregate.createIndexRecord(currentPos, initRecsSize));
                }
              }
            }
        }
    }
    /**
     * 'initial sheet records' are between INDEX and the 'Row Blocks'
     * @param bofRecordIndex index of record after which INDEX record is to be placed
     * @return count of bytes from end of INDEX record to first ROW record.
     */
    private int getSizeOfInitialSheetRecords(int bofRecordIndex) {

        int result = 0;
        // start just after BOF record (INDEX is not present in this list)
        for (int j = bofRecordIndex + 1; j < _records.size(); j++) {
            RecordBase tmpRec = _records.get(j);
            if (tmpRec instanceof RowRecordsAggregate) {
                break;
            }
            result += tmpRec.getRecordSize();
        }
        if (_isUncalced) {
            result += UncalcedRecord.getStaticRecordSize();
        }
        return result;
    }

    /**
     * Adds a value record to the sheet's contained binary records
     * (i.e. LabelSSTRecord or NumberRecord).
     * <P>
     * This method is "loc" sensitive.  Meaning you need to set LOC to where you
     * want it to start searching.  If you don't know do this: setLoc(getDimsLoc).
     * When adding several rows you can just start at the last one by leaving loc
     * at what this sets it to.
     *
     * @param row the row to add the cell value to
     * @param col the cell value record itself.
     */
    public void addValueRecord(int row, CellValueRecordInterface col) {

        LOGGER.atDebug().log("add value record row{}", box(row));
        DimensionsRecord d = _dimensions;

        if (col.getColumn() >= d.getLastCol()) {
            d.setLastCol(( short ) (col.getColumn() + 1));
        }
        if (col.getColumn() < d.getFirstCol()) {
            d.setFirstCol(col.getColumn());
        }
        _rowsAggregate.insertCell(col);
    }

    /**
     * remove a value record from the records array.
     *
     * This method is not loc sensitive, it resets loc to = dimsloc so no worries.
     *
     * @param row - the row of the value record you wish to remove
     * @param col - a record supporting the CellValueRecordInterface.
     * @see CellValueRecordInterface
     */
    public void removeValueRecord(int row, CellValueRecordInterface col) {

        LOGGER.atDebug().log("remove value record row {}", box(row));
        _rowsAggregate.removeCell(col);
    }

    /**
     * replace a value record from the records array.
     *
     * This method is not loc sensitive, it resets loc to = dimsloc so no worries.
     *
     * @param newval - a record supporting the CellValueRecordInterface.  this will replace
     *                the cell value with the same row and column.  If there isn't one, one will
     *                be added.
     */

    public void replaceValueRecord(CellValueRecordInterface newval) {

        LOGGER.atDebug().log("replaceValueRecord ");
        //The ValueRecordsAggregate use a tree map underneath.
        //The tree Map uses the CellValueRecordInterface as both the
        //key and the value, if we dont do a remove, then
        //the previous instance of the key is retained, effectively using
        //double the memory
        _rowsAggregate.removeCell(newval);
        _rowsAggregate.insertCell(newval);
    }

    /**
     * Adds a row record to the sheet
     *
     * <P>
     * This method is "loc" sensitive.  Meaning you need to set LOC to where you
     * want it to start searching.  If you don't know do this: setLoc(getDimsLoc).
     * When adding several rows you can just start at the last one by leaving loc
     * at what this sets it to.
     *
     * @param row the row record to be added
     */

    public void addRow(RowRecord row) {
        LOGGER.atDebug().log("addRow ");
        DimensionsRecord d = _dimensions;

        if (row.getRowNumber() >= d.getLastRow()) {
            d.setLastRow(row.getRowNumber() + 1);
        }
        if (row.getRowNumber() < d.getFirstRow()) {
            d.setFirstRow(row.getRowNumber());
        }

        //If the row exists remove it, so that any cells attached to the row are removed
        RowRecord existingRow = _rowsAggregate.getRow(row.getRowNumber());
        if (existingRow != null) {
            _rowsAggregate.removeRow(existingRow);
        }

        _rowsAggregate.insertRow(row);

        LOGGER.atDebug().log("exit addRow");
    }

    /**
     * Removes a row record
     *
     * This method is not loc sensitive, it resets loc to = dimsloc so no worries.
     *
     * @param row  the row record to remove
     */
    public void removeRow(RowRecord row) {
        _rowsAggregate.removeRow(row);
    }

    /**
     * Get all the value records (from LOC). Records will be returned from the first
     *  record (starting at LOC) which is a value record.
     *
     * <P>
     * This method is "loc" sensitive.  Meaning you need to set LOC to where you
     * want it to start searching.  If you don't know do this: setLoc(getDimsLoc).
     * When adding several rows you can just start at the last one by leaving loc
     * at what this sets it to.  For this method, set loc to dimsloc to start with,
     * subsequent calls will return values in (physical) sequence or NULL when you get to the end.
     *
     * @return Iterator of CellValueRecordInterface representing the value records
     */
    public Iterator<CellValueRecordInterface> getCellValueIterator(){
    	return _rowsAggregate.getCellValueIterator();
    }

    /**
     * get the NEXT RowRecord (from LOC).  The first record that is a Row record
     * (starting at LOC) will be returned.
     * <P>
     * This method is "loc" sensitive.  Meaning you need to set LOC to where you
     * want it to start searching.  If you don't know do this: setLoc(getDimsLoc).
     * When adding several rows you can just start at the last one by leaving loc
     * at what this sets it to.  For this method, set loc to dimsloc to start with.
     * subsequent calls will return rows in (physical) sequence or NULL when you get to the end.
     *
     * @return RowRecord representing the next row record or NULL if there are no more
     */
    public RowRecord getNextRow() {
        if (rowRecIterator == null)
        {
            rowRecIterator = _rowsAggregate.getIterator();
        }
        if (!rowRecIterator.hasNext())
        {
            return null;
        }
        return rowRecIterator.next();
    }

    /**
     * get the NEXT (from LOC) RowRecord where rownumber matches the given rownum.
     * The first record that is a Row record (starting at LOC) that has the
     * same rownum as the given rownum will be returned.
     * <P>
     * This method is "loc" sensitive.  Meaning you need to set LOC to where you
     * want it to start searching.  If you don't know do this: setLoc(getDimsLoc).
     * When adding several rows you can just start at the last one by leaving loc
     * at what this sets it to.  For this method, set loc to dimsloc to start with.
     * subsequent calls will return rows in (physical) sequence or NULL when you get to the end.
     *
     * @param rownum   which row to return (careful with LOC)
     * @return RowRecord representing the next row record or NULL if there are no more
     *
     */
    public RowRecord getRow(int rownum) {
        return _rowsAggregate.getRow(rownum);
    }

    /**
     * creates the BOF record
     */
    /* package */ static BOFRecord createBOF() {
        BOFRecord retval = new BOFRecord();

        retval.setVersion(( short ) 0x600);
        retval.setType(( short ) 0x010);

        retval.setBuild(( short ) 0x0dbb);
        retval.setBuildYear(( short ) 1996);
        retval.setHistoryBitMask(0xc1);
        retval.setRequiredVersion(0x6);
        return retval;
    }

    /**
     * creates the CalcMode record and sets it to 1 (automatic formula caculation)
     */
    private static CalcModeRecord createCalcMode() {
        CalcModeRecord retval = new CalcModeRecord();

        retval.setCalcMode(( short ) 1);
        return retval;
    }

    /**
     * creates the CalcCount record and sets it to 100 (default number of iterations)
     */
    private static CalcCountRecord createCalcCount() {
        CalcCountRecord retval = new CalcCountRecord();

        retval.setIterations(( short ) 100);   // default 100 iterations
        return retval;
    }

    /**
     * creates the RefMode record and sets it to A1 Mode (default reference mode)
     */
    private static RefModeRecord createRefMode() {
        RefModeRecord retval = new RefModeRecord();

        retval.setMode(RefModeRecord.USE_A1_MODE);
        return retval;
    }

    /**
     * creates the Iteration record and sets it to false (don't iteratively calculate formulas)
     */
    private static IterationRecord createIteration() {
        return new IterationRecord(false);
    }

    /**
     * creates the Delta record and sets it to 0.0010 (default accuracy)
     */
    private static DeltaRecord createDelta() {
        return new DeltaRecord(DeltaRecord.DEFAULT_VALUE);
    }

    /**
     * creates the SaveRecalc record and sets it to true (recalculate before saving)
     */
    private static SaveRecalcRecord createSaveRecalc() {
        SaveRecalcRecord retval = new SaveRecalcRecord();

        retval.setRecalc(true);
        return retval;
    }

    /**
     * creates the PrintHeaders record and sets it to false (we don't create headers yet so why print them)
     */
    private static PrintHeadersRecord createPrintHeaders() {
        PrintHeadersRecord retval = new PrintHeadersRecord();

        retval.setPrintHeaders(false);
        return retval;
    }

    /**
     * creates the PrintGridlines record and sets it to false (that makes for ugly sheets).  As far as I can
     * tell this does the same thing as the GridsetRecord
     */
    private static PrintGridlinesRecord createPrintGridlines() {
        PrintGridlinesRecord retval = new PrintGridlinesRecord();

        retval.setPrintGridlines(false);
        return retval;
    }

    /**
     * creates the Gridset record and sets it to true (user has mucked with the gridlines)
     */
    private static GridsetRecord createGridset() {
        GridsetRecord retval = new GridsetRecord();

        retval.setGridset(true);
        return retval;
    }

    /**
     * creates the Guts record and sets leftrow/topcol guttter and rowlevelmax/collevelmax to 0
      */
    private static GutsRecord createGuts() {
        GutsRecord retval = new GutsRecord();

        retval.setLeftRowGutter(( short ) 0);
        retval.setTopColGutter(( short ) 0);
        retval.setRowLevelMax(( short ) 0);
        retval.setColLevelMax(( short ) 0);
        return retval;
    }

    private GutsRecord getGutsRecord() {
        if (_gutsRecord == null) {
            GutsRecord result = createGuts();
            RecordOrderer.addNewSheetRecord(_records, result);
            _gutsRecord = result;
        }

        return _gutsRecord;
    }

    /**
     * creates the DefaultRowHeight Record and sets its options to 0 and rowheight to 0xff
     */
    private static DefaultRowHeightRecord createDefaultRowHeight() {
        DefaultRowHeightRecord retval = new DefaultRowHeightRecord();

        retval.setOptionFlags(( short ) 0);
        retval.setRowHeight(DefaultRowHeightRecord.DEFAULT_ROW_HEIGHT);
        return retval;
    }

    /**
     * creates the WSBoolRecord and sets its values to defaults
     */
    private static WSBoolRecord createWSBool() {
        WSBoolRecord retval = new WSBoolRecord();

        retval.setWSBool1(( byte ) 0x4);
        retval.setWSBool2(( byte ) 0xffffffc1);
        return retval;
    }


    /**
     * creates the DefaultColWidth Record and sets it to 8
      */
    private static DefaultColWidthRecord createDefaultColWidth() {
        DefaultColWidthRecord retval = new DefaultColWidthRecord();
        retval.setColWidth(DefaultColWidthRecord.DEFAULT_COLUMN_WIDTH);
        return retval;
    }

    /**
     * get the default column width for the sheet (if the columns do not define their own width)
     * @return default column width
     */
    public int getDefaultColumnWidth() {
        return defaultcolwidth.getColWidth();
    }

    /**
     * @return <code>true</code> if gridlines are printed
     */
    public boolean isGridsPrinted() {
        if (gridset == null) {
            gridset = createGridset();
            //Insert the newlycreated Gridset record at the end of the record (just before the EOF)
            int loc = findFirstRecordLocBySid(EOFRecord.sid);
            _records.add(loc, gridset);
        }
        return !gridset.getGridset();
    }

    /**
     * set whether gridlines printed or not.
     * @param value     True if gridlines printed.
     */
    public void setGridsPrinted(boolean value) {
        gridset.setGridset(!value);
    }

    /**
     * set the default column width for the sheet (if the columns do not define their own width)
     * @param dcw  default column width
     */
    public void setDefaultColumnWidth(int dcw) {
        defaultcolwidth.setColWidth(dcw);
    }

    /**
     * set the default row height for the sheet (if the rows do not define their own height)
     *
     * @param dch the default row height
     */
    public void setDefaultRowHeight(short dch) {
        defaultrowheight.setRowHeight(dch);
        // set the bit that specifies that the default settings for the row height have been changed.
        defaultrowheight.setOptionFlags((short)1);
    }

    /**
     * get the default row height for the sheet (if the rows do not define their own height)
     * @return  default row height
     */
    public short getDefaultRowHeight() {
        return defaultrowheight.getRowHeight();
    }

    /**
     * get the width of a given column in units of 1/256th of a character width
     * @param columnIndex index
     * @see DefaultColWidthRecord
     * @see ColumnInfoRecord
     * @see #setColumnWidth(int, int)
     * @return column width in units of 1/256th of a character width
     */
    public int getColumnWidth(int columnIndex) {

        ColumnInfoRecord ci = _columnInfos.findColumnInfo(columnIndex);
        if (ci != null) {
            return ci.getColumnWidth();
        }
        //default column width is measured in characters
        //multiply
        return (256*defaultcolwidth.getColWidth());
    }

    /**
     * get the index to the ExtendedFormatRecord "associated" with
     * the column at specified 0-based index. (In this case, an
     * ExtendedFormatRecord index is actually associated with a
     * ColumnInfoRecord which spans 1 or more columns)
     * <p>
     * Returns the index to the default ExtendedFormatRecord (0xF)
     * if no ColumnInfoRecord exists that includes the column
     * index specified.
     * @param columnIndex the column index
     * @return index of ExtendedFormatRecord associated with
     * ColumnInfoRecord that includes the column index or the
     * index of the default ExtendedFormatRecord (0xF)
     */
    public short getXFIndexForColAt(short columnIndex) {
        ColumnInfoRecord ci = _columnInfos.findColumnInfo(columnIndex);
        if (ci != null) {
            return (short)ci.getXFIndex();
        }
        return 0xF;
    }

    /**
     * set the width for a given column in 1/256th of a character width units
     *
     * @param column -
     *            the column number
     * @param width
     *            (in units of 1/256th of a character width)
     */
    public void setColumnWidth(int column, int width) {
        if(width > 255*256) throw new IllegalArgumentException("The maximum column width for an individual cell is 255 characters.");

        setColumn(column, null, Integer.valueOf(width), null, null, null);
    }

    /**
     * Get the hidden property for a given column.
     * @param columnIndex column index
     * @see DefaultColWidthRecord
     * @see ColumnInfoRecord
     * @see #setColumnHidden(int, boolean)
     * @return whether the column is hidden or not.
     */
    public boolean isColumnHidden(int columnIndex) {
        ColumnInfoRecord cir = _columnInfos.findColumnInfo(columnIndex);
        if (cir == null) {
            return false;
        }
        return cir.getHidden();
    }

    /**
     * Get the hidden property for a given column.
     * @param column - the column number
     * @param hidden - whether the column is hidden or not
     */
    public void setColumnHidden(int column, boolean hidden) {
        setColumn( column, null, null, null, Boolean.valueOf(hidden), null);
    }
    public void setDefaultColumnStyle(int column, int styleIndex) {
        setColumn(column, Short.valueOf((short)styleIndex), null, null, null, null);
    }

    private void setColumn(int column, Short xfStyle, Integer width, Integer level, Boolean hidden, Boolean collapsed) {
        _columnInfos.setColumn( column, xfStyle, width, level, hidden, collapsed );
    }


    /**
     * Creates an outline group for the specified columns.
     * @param fromColumn    group from this column (inclusive)
     * @param toColumn      group to this column (inclusive)
     * @param indent        if true the group will be indented by one level,
     *                      if false indenting will be removed by one level.
     */
    public void groupColumnRange(int fromColumn, int toColumn, boolean indent) {

        // Set the level for each column
        _columnInfos.groupColumnRange( fromColumn, toColumn, indent);

        // Determine the maximum overall level
        int maxLevel = _columnInfos.getMaxOutlineLevel();

        GutsRecord guts = getGutsRecord();
        guts.setColLevelMax( (short) ( maxLevel+1 ) );
        if (maxLevel == 0) {
            guts.setTopColGutter( (short)0 );
        } else {
            guts.setTopColGutter( (short) ( 29 + (12 * (maxLevel-1)) ) );
        }
    }

    /**
     * creates the Dimensions Record and sets it to bogus values (you should set this yourself
     * or let the high level API do it for you)
     */
    private static DimensionsRecord createDimensions() {
        DimensionsRecord retval = new DimensionsRecord();

        retval.setFirstCol(( short ) 0);
        retval.setLastRow(1);             // one more than it is
        retval.setFirstRow(0);
        retval.setLastCol(( short ) 1);   // one more than it is
        return retval;
    }

    /**
     * creates the WindowTwo Record and sets it to:  <P>
     * options        = 0x6b6 <P>
     * toprow         = 0 <P>
     * leftcol        = 0 <P>
     * headercolor    = 0x40 <P>
     * pagebreakzoom  = 0x0 <P>
     * normalzoom     = 0x0 <p>
     */
    private static WindowTwoRecord createWindowTwo() {
        WindowTwoRecord retval = new WindowTwoRecord();

        retval.setOptions(( short ) 0x6b6);
        retval.setTopRow(( short ) 0);
        retval.setLeftCol(( short ) 0);
        retval.setHeaderColor(0x40);
        retval.setPageBreakZoom(( short ) 0);
        retval.setNormalZoom(( short ) 0);
        return retval;
    }

    /**
     * Creates the Selection record and sets it to nothing selected
    */
    private static SelectionRecord createSelection() {
        return new SelectionRecord(0, 0);
    }

    public short getTopRow() {
        return (windowTwo==null) ? (short) 0 : windowTwo.getTopRow();
    }

    public void setTopRow(short topRow) {
        if (windowTwo!=null) {
            windowTwo.setTopRow(topRow);
        }
    }

    /**
     * Sets the left column to show in desktop window pane.
     * @param leftCol the left column to show in desktop window pane
     */
    public void setLeftCol(short leftCol) {
        if (windowTwo!=null) {
            windowTwo.setLeftCol(leftCol);
        }
    }

    public short getLeftCol() {
        return (windowTwo==null) ? (short) 0 : windowTwo.getLeftCol();
    }

    /**
     * Returns the active row
     *
     * @see SelectionRecord
     * @return row the active row index
     */
    public int getActiveCellRow() {
        if (_selection == null) {
            return 0;
        }
        return _selection.getActiveCellRow();
    }

    /**
     * Sets the active row
     *
     * @param row the row index
     * @see SelectionRecord
     */
    public void setActiveCellRow(int row) {
        //shouldn't have a sheet w/o a SelectionRecord, but best to guard anyway
        if (_selection != null) {
            _selection.setActiveCellRow(row);
        }
    }

    /**
     * @see SelectionRecord
     * @return column of the active cell
     */
    public short getActiveCellCol() {
        if (_selection == null) {
            return 0;
        }
        return (short)_selection.getActiveCellCol();
    }

    /**
     * Sets the active column
     *
     * @param col the column index
     * @see SelectionRecord
     */
    public void setActiveCellCol(short col) {
        //shouldn't have a sheet w/o a SelectionRecord, but best to guard anyway
        if (_selection != null)
        {
            _selection.setActiveCellCol(col);
        }
    }

    public List<RecordBase> getRecords() {
        return _records;
    }

    /**
     * Gets the gridset record for this sheet.
     *
     * @return the gridset record for this sheet
     */
    public GridsetRecord getGridsetRecord()
    {
        return gridset;
    }

    /**
     * Returns the first occurrence of a record matching a particular sid.
     *
     * @param sid the sid to search for
     *
     * @return the matching record or {@code null} if it wasn't found
     */
    public Record findFirstRecordBySid(short sid) {
        int ix = findFirstRecordLocBySid(sid);
        if (ix < 0) {
            return null;
        }
        return (Record) _records.get(ix);
    }

    /**
     * Sets the SCL record or creates it in the correct place if it does not
     * already exist.
     *
     * @param sclRecord     The record to set.
     */
    public void setSCLRecord(SCLRecord sclRecord) {
        int oldRecordLoc = findFirstRecordLocBySid(SCLRecord.sid);
        if (oldRecordLoc == -1) {
            // Insert it after the window record
            int windowRecordLoc = findFirstRecordLocBySid(WindowTwoRecord.sid);
            _records.add(windowRecordLoc+1, sclRecord);
        } else {
            _records.set(oldRecordLoc, sclRecord);
        }
    }

    /**
     * Finds the first occurrence of a record matching a particular sid and
     * returns it's position.
     * @param sid   the sid to search for
     * @return  the record position of the matching record or -1 if no match
     *          is made.
     */
    public int findFirstRecordLocBySid( short sid ) { // TODO - remove this method
        int max = _records.size();
        for (int i=0; i< max; i++) {
            Object rb = _records.get(i);
            if (!(rb instanceof Record)) {
                continue;
            }
            Record record = (Record) rb;
            if (record.getSid() == sid) {
                return i;
            }
        }
        return -1;
    }

    public WindowTwoRecord getWindowTwo() {
        return windowTwo;
    }

    /**
     * Returns the PrintGridlinesRecord.
     * @return PrintGridlinesRecord for the sheet.
     */
    public PrintGridlinesRecord getPrintGridlines ()
    {
        return printGridlines;
    }

    /**
     * Sets the PrintGridlinesRecord.
     * @param newPrintGridlines The new PrintGridlinesRecord for the sheet.
     */
    public void setPrintGridlines (PrintGridlinesRecord newPrintGridlines)
    {
        printGridlines = newPrintGridlines;
    }

    /**
     * Returns the PrintHeadersRecord.
     * @return PrintHeadersRecord for the sheet.
     */
    public PrintHeadersRecord getPrintHeaders()
    {
        return printHeaders;
    }

    /**
     * Sets the PrintHeadersRecord.
     * @param newPrintHeaders The new PrintHeadersRecord for the sheet.
     */
    public void setPrintHeaders(PrintHeadersRecord newPrintHeaders)
    {
        printHeaders = newPrintHeaders;
    }

    /**
     * Sets whether the sheet is selected
     * @param sel True to select the sheet, false otherwise.
     */
    public void setSelected(boolean sel) {
        windowTwo.setSelected(sel);
    }

    /**
     * Creates a split (freezepane). Any existing freezepane or split pane is overwritten.
     *
     * <p>If both colSplit and rowSplit are zero then the existing freeze pane is removed</p>
     *
     * @param colSplit      Horizonatal position of split.
     * @param rowSplit      Vertical position of split.
     * @param topRow        Top row visible in bottom pane
     * @param leftmostColumn   Left column visible in right pane.
     */
    public void createFreezePane(int colSplit, int rowSplit, int topRow, int leftmostColumn) {
        int paneLoc = findFirstRecordLocBySid(PaneRecord.sid);
        if (paneLoc != -1)
            _records.remove(paneLoc);

        // If both colSplit and rowSplit are zero then the existing freeze pane is removed
        if(colSplit == 0 && rowSplit == 0){
            windowTwo.setFreezePanes(false);
            windowTwo.setFreezePanesNoSplit(false);
            SelectionRecord sel = (SelectionRecord) findFirstRecordBySid(SelectionRecord.sid);
            if (sel != null) {
                sel.setPane(PaneInformation.PANE_UPPER_LEFT);
            }
            return;
        }

        int loc = findFirstRecordLocBySid(WindowTwoRecord.sid);
        PaneRecord pane = new PaneRecord();
        pane.setX((short)colSplit);
        pane.setY((short)rowSplit);
        pane.setTopRow((short) topRow);
        pane.setLeftColumn((short) leftmostColumn);
        if (rowSplit == 0) {
            pane.setTopRow((short)0);
            pane.setActivePane((short)1);
        } else if (colSplit == 0) {
            pane.setLeftColumn((short)0);
            pane.setActivePane((short)2);
        } else {
            pane.setActivePane((short)0);
        }
        _records.add(loc+1, pane);

        windowTwo.setFreezePanes(true);
        windowTwo.setFreezePanesNoSplit(true);

        SelectionRecord sel = (SelectionRecord) findFirstRecordBySid(SelectionRecord.sid);
        if (sel != null) {
            sel.setPane((byte) pane.getActivePane());
        }
    }

    /**
     * Creates a split pane. Any existing freezepane or split pane is overwritten.
     * @param xSplitPos      Horizonatal position of split (in 1/20th of a point).
     * @param ySplitPos      Vertical position of split (in 1/20th of a point).
     * @param topRow        Top row visible in bottom pane
     * @param leftmostColumn   Left column visible in right pane.
     * @param activePane    Active pane.  One of: PANE_LOWER_RIGHT,
     *                      PANE_UPPER_RIGHT, PANE_LOWER_LEFT, PANE_UPPER_LEFT
     * @see #PANE_LOWER_LEFT
     * @see #PANE_LOWER_RIGHT
     * @see #PANE_UPPER_LEFT
     * @see #PANE_UPPER_RIGHT
     */
    public void createSplitPane(int xSplitPos, int ySplitPos, int topRow, int leftmostColumn, int activePane) {
        int paneLoc = findFirstRecordLocBySid(PaneRecord.sid);
        if (paneLoc != -1)
            _records.remove(paneLoc);

        int loc = findFirstRecordLocBySid(WindowTwoRecord.sid);
        PaneRecord r = new PaneRecord();
        r.setX((short)xSplitPos);
        r.setY((short)ySplitPos);
        r.setTopRow((short) topRow);
        r.setLeftColumn((short) leftmostColumn);
        r.setActivePane((short) activePane);
        _records.add(loc+1, r);

        windowTwo.setFreezePanes(false);
        windowTwo.setFreezePanesNoSplit(false);

        SelectionRecord sel = (SelectionRecord) findFirstRecordBySid(SelectionRecord.sid);
        if (sel != null) {
            sel.setPane(PANE_LOWER_RIGHT);
        }

    }

    /**
     * Returns the information regarding the currently configured pane (split or freeze).
     * @return <code>null</code> if no pane configured, or the pane information.
     */
    public PaneInformation getPaneInformation() {
      PaneRecord rec = (PaneRecord)findFirstRecordBySid(PaneRecord.sid);
      if (rec == null)
        return null;

      return new PaneInformation(rec.getX(), rec.getY(), rec.getTopRow(),
                                 rec.getLeftColumn(), (byte)rec.getActivePane(), windowTwo.getFreezePanes());
    }

    public SelectionRecord getSelection() {
        return _selection;
    }

    public void setSelection( SelectionRecord selection) {
        _selection = selection;
    }

    /**
     * @return the {@link WorksheetProtectionBlock} for this sheet
     */
    public WorksheetProtectionBlock getProtectionBlock() {
        return _protectionBlock;
    }
    /**
     * Sets whether the gridlines are shown in a viewer.
     * @param show whether to show gridlines or not
     */
    public void setDisplayGridlines(boolean show) {
        windowTwo.setDisplayGridlines(show);
    }

    /**
     * @return <code>true</code> if gridlines are displayed
     */
    public boolean isDisplayGridlines() {
    return windowTwo.getDisplayGridlines();
    }

    /**
     * Sets whether the formulas are shown in a viewer.
     * @param show whether to show formulas or not
     */
    public void setDisplayFormulas(boolean show) {
        windowTwo.setDisplayFormulas(show);
    }

    /**
     * Returns if formulas are displayed.
     * @return whether formulas are displayed
     */
    public boolean isDisplayFormulas() {
    return windowTwo.getDisplayFormulas();
    }

    /**
     * Sets whether the RowColHeadings are shown in a viewer.
     * @param show whether to show RowColHeadings or not
     */
    public void setDisplayRowColHeadings(boolean show) {
        windowTwo.setDisplayRowColHeadings(show);
    }

    /**
     * Returns if RowColHeadings are displayed.
     * @return whether RowColHeadings are displayed
     */
    public boolean isDisplayRowColHeadings() {
        return windowTwo.getDisplayRowColHeadings();
    }

    /**
     * Sets whether the RowColHeadings are shown in a viewer.
     * @param show whether to show RowColHeadings or not
     */
    public void setPrintRowColHeadings(boolean show) {
        windowTwo.setDisplayRowColHeadings(show);
    }

    /**
     * Returns if RowColHeadings are displayed.
     * @return whether RowColHeadings are displayed
     */
    public boolean isPrintRowColHeadings() {
        return windowTwo.getDisplayRowColHeadings();
    }


    /**
     * @return whether an uncalced record must be inserted or not at generation
     */
    public boolean getUncalced() {
        return _isUncalced;
    }
    /**
     * @param uncalced whether an uncalced record must be inserted or not at generation
     */
    public void setUncalced(boolean uncalced) {
        this._isUncalced = uncalced;
    }

    /**
     * Finds the DrawingRecord for our sheet, and
     *  attaches it to the DrawingManager (which knows about
     *  the overall DrawingGroup for our workbook).
     * If requested, will create a new DrawRecord
     *  if none currently exist
     * @param drawingManager The DrawingManager2 for our workbook
     * @param createIfMissing Should one be created if missing?
     * @return location of EscherAggregate record. if no EscherAggregate record is found return -1
     */
    public int aggregateDrawingRecords(DrawingManager2 drawingManager, boolean createIfMissing) {
        int loc = findFirstRecordLocBySid(DrawingRecord.sid);
        boolean noDrawingRecordsFound = (loc == -1);
        if (noDrawingRecordsFound) {
            if(!createIfMissing) {
                // None found, and not allowed to add in
                return -1;
            }

            EscherAggregate aggregate = new EscherAggregate(true);
            loc = findFirstRecordLocBySid(EscherAggregate.sid);
            if (loc == -1) {
                loc = findFirstRecordLocBySid( WindowTwoRecord.sid );
            } else {
                getRecords().remove(loc);
            }
            getRecords().add( loc, aggregate );
            return loc;
        }
        List<RecordBase> records = getRecords();

        EscherAggregate.createAggregate(records, loc);

        return loc;
    }

    /**
     * Perform any work necessary before the sheet is about to be serialized.
     * For instance the escher aggregates size needs to be calculated before
     * serialization so that the dgg record (which occurs first) can be written.
     */
    public void preSerialize() {
        for (RecordBase r: getRecords()) {
            if (r instanceof EscherAggregate) {
                // Trigger flattening of user model and corresponding update of dgg record.
                r.getRecordSize();
            }
        }
    }


    public PageSettingsBlock getPageSettings() {
        if (_psBlock == null) {
            _psBlock = new PageSettingsBlock();
            RecordOrderer.addNewSheetRecord(_records, _psBlock);
        }
        return _psBlock;
    }


    public void setColumnGroupCollapsed(int columnNumber, boolean collapsed) {
        if (collapsed) {
            _columnInfos.collapseColumn(columnNumber);
        } else {
            _columnInfos.expandColumn(columnNumber);
        }
    }


    public void groupRowRange(int fromRow, int toRow, boolean indent)
    {
        for (int rowNum = fromRow; rowNum <= toRow; rowNum++)
        {
            RowRecord row = getRow( rowNum );
            if (row == null)
            {
                row = RowRecordsAggregate.createRow(rowNum);
                addRow( row );
            }
            int level = row.getOutlineLevel();
            if (indent) level++; else level--;
            level = Math.max(0, level);
            level = Math.min(7, level);
            row.setOutlineLevel((short) ( level ));
        }

        recalcRowGutter();
    }

    private void recalcRowGutter() {
        int maxLevel = 0;
        Iterator<RowRecord> iterator = _rowsAggregate.getIterator();
        while (iterator.hasNext()) {
            RowRecord rowRecord = iterator.next();
            maxLevel = Math.max(rowRecord.getOutlineLevel(), maxLevel);
        }

        // Grab the guts record, adding if needed
        GutsRecord guts = getGutsRecord();
        // Set the levels onto it
        guts.setRowLevelMax( (short) ( maxLevel + 1 ) );
        guts.setLeftRowGutter( (short) ( 29 + (12 * (maxLevel)) ) );
    }

    public DataValidityTable getOrCreateDataValidityTable() {
        if (_dataValidityTable == null) {
            DataValidityTable result = new DataValidityTable();
            RecordOrderer.addNewSheetRecord(_records, result);
            _dataValidityTable = result;
        }
        return _dataValidityTable;
    }
    /**
     * Get the {@link NoteRecord}s (related to cell comments) for this sheet
     * @return never <code>null</code>, typically empty array
     */
    public NoteRecord[] getNoteRecords() {
        List<NoteRecord> temp = new ArrayList<>();
        for(int i=_records.size()-1; i>=0; i--) {
            RecordBase rec = _records.get(i);
            if (rec instanceof NoteRecord) {
                temp.add((NoteRecord) rec);
            }
        }
        if (temp.size() < 1) {
            return NoteRecord.EMPTY_ARRAY;
        }
        NoteRecord[] result = new NoteRecord[temp.size()];
        temp.toArray(result);
        return result;
    }

    public int getColumnOutlineLevel(int columnIndex) {
        return _columnInfos.getOutlineLevel(columnIndex);
    }

    public int getMinColumnIndex() {
        return _columnInfos.getMinColumnIndex();
    }

    public int getMaxColumnIndex() {
        return _columnInfos.getMaxColumnIndex();
    }
}
