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

import java.util.Iterator;
import java.util.NoSuchElementException;

import org.apache.poi.hssf.record.CellValueRecordInterface;
import org.apache.poi.hssf.record.ExtendedFormatRecord;
import org.apache.poi.hssf.record.RowRecord;
import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.util.Configurator;

/**
 * High level representation of a row of a spreadsheet.
 *
 * Only rows that have cells should be added to a Sheet.
 */
public final class HSSFRow implements Row, Comparable<HSSFRow> {

    // used for collections
    public final static int INITIAL_CAPACITY = Configurator.getIntValue("HSSFRow.ColInitialCapacity", 5);

    private int rowNum;
    private HSSFCell[] cells;

    /**
     * reference to low level representation
     */
    private final RowRecord row;

    /**
     * reference to containing low level Workbook
     */
    private final HSSFWorkbook book;

    /**
     * reference to containing Sheet
     */
    private final HSSFSheet sheet;

    /**
     * Creates new HSSFRow from scratch. Only HSSFSheet should do this.
     *
     * @param book low-level Workbook object containing the sheet that contains this row
     * @param sheet low-level Sheet object that contains this Row
     * @param rowNum the row number of this row (0 based)
     * @see org.apache.poi.hssf.usermodel.HSSFSheet#createRow(int)
     */
    HSSFRow(HSSFWorkbook book, HSSFSheet sheet, int rowNum) {
        this(book, sheet, new RowRecord(rowNum));
    }

    /**
     * Creates an HSSFRow from a low level RowRecord object.  Only HSSFSheet should do
     * this.  HSSFSheet uses this when an existing file is read in.
     *
     * @param book low-level Workbook object containing the sheet that contains this row
     * @param sheet low-level Sheet object that contains this Row
     * @param record the low level api object this row should represent
     * @see org.apache.poi.hssf.usermodel.HSSFSheet#createRow(int)
     */
    HSSFRow(HSSFWorkbook book, HSSFSheet sheet, RowRecord record) {
        this.book = book;
        this.sheet = sheet;
        row = record;
        setRowNum(record.getRowNumber());
        
        // Size the initial cell list such that a read only case won't waste
        //  lots of memory, and a create/read followed by adding new cells can
        //  add a bit without needing a resize
        cells = new HSSFCell[record.getLastCol()+INITIAL_CAPACITY];
        
        // Don't trust colIx boundaries as read by other apps
        // set the RowRecord empty for the moment
        record.setEmpty();
        // subsequent calls to createCellFromRecord() will update the colIx boundaries properly
    }

    /**
     * Use this to create new cells within the row and return it.
     * <p>
     * The cell that is returned is a {@link CellType#BLANK}. The type can be changed
     * either through calling <code>setCellValue</code> or <code>setCellType</code>.
     *
     * @param column - the column number this cell represents
     *
     * @return HSSFCell a high level representation of the created cell.
     * @throws IllegalArgumentException if columnIndex < 0 or greater than 255,
     *   the maximum number of columns supported by the Excel binary format (.xls)
     */
    @Override
    public HSSFCell createCell(int column)
    {
        return this.createCell(column,CellType.BLANK);
    }
    
    /**
     * Use this to create new cells within the row and return it.
     * <p>
     * The cell that is returned will be of the requested type.
     * The type can be changed either through calling setCellValue 
     *  or setCellType, but there is a small overhead to doing this,
     *  so it is best to create the required type up front.
     *
     * @param columnIndex - the column number this cell represents
     *
     * @return HSSFCell a high level representation of the created cell.
     * @throws IllegalArgumentException if columnIndex < 0 or greater than 255,
     *   the maximum number of columns supported by the Excel binary format (.xls)
     * @deprecated POI 3.15 beta 3
     */
    @Override
    public HSSFCell createCell(int columnIndex, int type)
    {
        return createCell(columnIndex, CellType.forInt(type));
    }
    /**
     * Use this to create new cells within the row and return it.
     * <p>
     * The cell that is returned will be of the requested type.
     * The type can be changed either through calling setCellValue 
     *  or setCellType, but there is a small overhead to doing this,
     *  so it is best to create the required type up front.
     *
     * @param columnIndex - the column number this cell represents
     *
     * @return HSSFCell a high level representation of the created cell.
     * @throws IllegalArgumentException if columnIndex < 0 or greater than 255,
     *   the maximum number of columns supported by the Excel binary format (.xls)
     */
    @Override
    public HSSFCell createCell(int columnIndex, CellType type)
    {
        short shortCellNum = (short)columnIndex;
        if(columnIndex > 0x7FFF) {
            shortCellNum = (short)(0xffff - columnIndex);
        }

        HSSFCell cell = new HSSFCell(book, sheet, getRowNum(), shortCellNum, type);
        addCell(cell);
        sheet.getSheet().addValueRecord(getRowNum(), cell.getCellValueRecord());
        return cell;
    }

    /**
     * remove the HSSFCell from this row.
     * @param cell to remove
     */
    @Override
    public void removeCell(Cell cell) {
        if(cell == null) {
            throw new IllegalArgumentException("cell must not be null");
        }
        removeCell((HSSFCell)cell, true);
    }
    private void removeCell(HSSFCell cell, boolean alsoRemoveRecords) {

        int column=cell.getColumnIndex();
        if(column < 0) {
            throw new RuntimeException("Negative cell indexes not allowed");
        }
        if(column >= cells.length || cell != cells[column]) {
            throw new RuntimeException("Specified cell is not from this row");
        }
        if(cell.isPartOfArrayFormulaGroup()){
            cell.notifyArrayFormulaChanging();
        }

        cells[column]=null;

        if(alsoRemoveRecords) {
            CellValueRecordInterface cval = cell.getCellValueRecord();
            sheet.getSheet().removeValueRecord(getRowNum(), cval);
        }
        if (cell.getColumnIndex()+1 == row.getLastCol()) {
            row.setLastCol(calculateNewLastCellPlusOne(row.getLastCol()));
        }
        if (cell.getColumnIndex() == row.getFirstCol()) {
            row.setFirstCol(calculateNewFirstCell(row.getFirstCol()));
        }
    }

    /**
     * Removes all the cells from the row, and their
     *  records too.
     */
    protected void removeAllCells() {
        for (HSSFCell cell : cells) {
            if (cell != null) {
                removeCell(cell, true);
            }
        }
        cells=new HSSFCell[INITIAL_CAPACITY];
    }

    /**
     * create a high level HSSFCell object from an existing low level record.  Should
     * only be called from HSSFSheet or HSSFRow itself.
     * @param cell low level cell to create the high level representation from
     * @return HSSFCell representing the low level record passed in
     */
    HSSFCell createCellFromRecord(CellValueRecordInterface cell) {
        HSSFCell hcell = new HSSFCell(book, sheet, cell);

        addCell(hcell);
        int colIx = cell.getColumn();
        if (row.isEmpty()) {
            row.setFirstCol(colIx);
            row.setLastCol(colIx + 1);
        } else {
            if (colIx < row.getFirstCol()) {
                row.setFirstCol(colIx);
            } else if (colIx > row.getLastCol()) {
                row.setLastCol(colIx + 1);
            } /*else {
                // added cell is within first and last cells
            }*/
        }
        // TODO - RowRecord column boundaries need to be updated for cell comments too
        return hcell;
    }

    /**
     * set the row number of this row.
     * @param rowIndex  the row number (0-based)
     * @throws IndexOutOfBoundsException if the row number is not within the range 0-65535.
     */
    @Override
    public void setRowNum(int rowIndex) {
        int maxrow = SpreadsheetVersion.EXCEL97.getLastRowIndex();
        if ((rowIndex < 0) || (rowIndex > maxrow)) {
          throw new IllegalArgumentException("Invalid row number (" + rowIndex
                  + ") outside allowable range (0.." + maxrow + ")");
        }
        rowNum = rowIndex;
        if (row != null) {
            row.setRowNumber(rowIndex);   // used only for KEY comparison (HSSFRow)
        }
    }

    /**
     * get row number this row represents
     * @return the row number (0 based)
     */
    @Override
    public int getRowNum()
    {
        return rowNum;
    }

    /**
     * Returns the HSSFSheet this row belongs to
     *
     * @return the HSSFSheet that owns this row
     */
    @Override
    public HSSFSheet getSheet()
    {
        return sheet;
    }

    /**
     * Returns the rows outline level. Increased as you
     *  put it into more groups (outlines), reduced as
     *  you take it out of them.
     */
    @Override
    public int getOutlineLevel() {
        return row.getOutlineLevel();
    }

    /**
     * Moves the supplied cell to a new column, which
     *  must not already have a cell there!
     * @param cell The cell to move
     * @param newColumn The new column number (0 based)
     */
    public void moveCell(HSSFCell cell, short newColumn) {
        // Ensure the destination is free
        if(cells.length > newColumn && cells[newColumn] != null) {
            throw new IllegalArgumentException("Asked to move cell to column " + newColumn + " but there's already a cell there");
        }

        // Check it's one of ours
        if(! cells[cell.getColumnIndex()].equals(cell)) {
            throw new IllegalArgumentException("Asked to move a cell, but it didn't belong to our row");
        }

        // Move the cell to the new position
        // (Don't remove the records though)
        removeCell(cell, false);
        cell.updateCellNum(newColumn);
        addCell(cell);
    }

    /**
     * used internally to add a cell.
     */
    private void addCell(HSSFCell cell) {

        int column=cell.getColumnIndex();
        // re-allocate cells array as required.
        if(column>=cells.length) {
            HSSFCell[] oldCells=cells;
            // New size based on the same logic as ArrayList
            int newSize=oldCells.length*3/2+1;
            if(newSize<column+1) {
                newSize=column+INITIAL_CAPACITY;
            }
            cells=new HSSFCell[newSize];
            System.arraycopy(oldCells,0,cells,0,oldCells.length);
        }
        cells[column]=cell;

        // fix up firstCol and lastCol indexes
        if (row.isEmpty() || column < row.getFirstCol()) {
            row.setFirstCol((short)column);
        }

        if (row.isEmpty() || column >= row.getLastCol()) {
            row.setLastCol((short) (column+1)); // +1 -> for one past the last index
        }
    }

    /**
     * Get the hssfcell representing a given column (logical cell)
     *  0-based. If you ask for a cell that is not defined, then
     *  you get a null.
     * This is the basic call, with no policies applied
     *
     * @param cellIndex  0 based column number
     * @return HSSFCell representing that column or null if undefined.
     */
    private HSSFCell retrieveCell(int cellIndex) {
        if(cellIndex<0||cellIndex>=cells.length) {
            return null;
        }
        return cells[cellIndex];
    }

    /**
     * Get the hssfcell representing a given column (logical cell)
     *  0-based.  If you ask for a cell that is not defined then
     *  you get a null, unless you have set a different
     *  {@link org.apache.poi.ss.usermodel.Row.MissingCellPolicy} on the base workbook.
     *
     * @param cellnum  0 based column number
     * @return HSSFCell representing that column or null if undefined.
     */
    @Override
    public HSSFCell getCell(int cellnum) {
        return getCell(cellnum, book.getMissingCellPolicy());
    }

    /**
     * Get the hssfcell representing a given column (logical cell)
     *  0-based.  If you ask for a cell that is not defined, then
     *  your supplied policy says what to do
     *
     * @param cellnum  0 based column number
     * @param policy Policy on blank / missing cells
     * @return representing that column or null if undefined + policy allows.
     */
    @Override
    public HSSFCell getCell(int cellnum, MissingCellPolicy policy) {
        HSSFCell cell = retrieveCell(cellnum);
        switch (policy) {
            case RETURN_NULL_AND_BLANK:
                return cell;
            case RETURN_BLANK_AS_NULL:
                boolean isBlank = (cell != null && cell.getCellTypeEnum() == CellType.BLANK);
                return (isBlank) ? null : cell;
            case CREATE_NULL_AS_BLANK:
                return (cell == null) ? createCell(cellnum, CellType.BLANK) : cell;
            default:
                throw new IllegalArgumentException("Illegal policy " + policy + " (" + policy.id + ")");
        }
    }

    /**
     * get the number of the first cell contained in this row.
     * @return short representing the first logical cell in the row, or -1 if the row does not contain any cells.
     */
    @Override
    public short getFirstCellNum() {
        if (row.isEmpty()) {
            return -1;
        }
        return (short) row.getFirstCol();
    }

    /**
     * Gets the index of the last cell contained in this row <b>PLUS ONE</b>. The result also
     * happens to be the 1-based column number of the last cell.  This value can be used as a
     * standard upper bound when iterating over cells:
     * <pre>
     * short minColIx = row.getFirstCellNum();
     * short maxColIx = row.getLastCellNum();
     * for(short colIx=minColIx; colIx&lt;maxColIx; colIx++) {
     *   HSSFCell cell = row.getCell(colIx);
     *   if(cell == null) {
     *     continue;
     *   }
     *   //... do something with cell
     * }
     * </pre>
     *
     * @return short representing the last logical cell in the row <b>PLUS ONE</b>, or -1 if the
     *  row does not contain any cells.
     */
    @Override
    public short getLastCellNum() {
        if (row.isEmpty()) {
            return -1;
        }
        return (short) row.getLastCol();
    }


    /**
     * gets the number of defined cells (NOT number of cells in the actual row!).
     * That is to say if only columns 0,4,5 have values then there would be 3.
     * @return int representing the number of defined cells in the row.
     */

    @Override
    public int getPhysicalNumberOfCells()
    {
        int count = 0;
        for (HSSFCell cell : cells) {
            if (cell != null) count++;
        }
        return count;
    }

    /**
     * set the row's height or set to ff (-1) for undefined/default-height.  Set the height in "twips" or
     * 1/20th of a point.
     * @param height  rowheight or -1 for undefined (use sheet default)
     */

    @Override
    public void setHeight(short height)
    {
        if(height == -1){
            row.setHeight((short)(0xFF | 0x8000));
            row.setBadFontHeight(false);
        } else {
            row.setBadFontHeight(true);
            row.setHeight(height);
        }
    }

    /**
     * set whether or not to display this row with 0 height
     * @param zHeight  height is zero or not.
     */
    @Override
    public void setZeroHeight(boolean zHeight) {
        row.setZeroHeight(zHeight);
    }

    /**
     * get whether or not to display this row with 0 height
     * @return - zHeight height is zero or not.
     */
    @Override
    public boolean getZeroHeight() {
        return row.getZeroHeight();
    }

    /**
     * set the row's height in points.
     * @param height  row height in points, <code>-1</code> means to use the default height
     */

    @Override
    public void setHeightInPoints(float height)
    {
        if(height == -1){
            row.setHeight((short)(0xFF | 0x8000));
            row.setBadFontHeight(false);
        } else {
            row.setBadFontHeight(true);
            row.setHeight((short) (height * 20));
        }
    }

    /**
     * get the row's height or ff (-1) for undefined/default-height in twips (1/20th of a point)
     * @return rowheight or 0xff for undefined (use sheet default)
     */

    @Override
    public short getHeight()
    {
        short height = row.getHeight();

        //The low-order 15 bits contain the row height.
        //The 0x8000 bit indicates that the row is standard height (optional)
        if ((height & 0x8000) != 0) height = sheet.getSheet().getDefaultRowHeight();
        else height &= 0x7FFF;

        return height;
    }

    /**
     * get the row's height or ff (-1) for undefined/default-height in points (20*getHeight())
     * @return rowheight or 0xff for undefined (use sheet default)
     */

    @Override
    public float getHeightInPoints()
    {
        return ((float)getHeight() / 20);
    }

    /**
     * get the lowlevel RowRecord represented by this object - should only be called
     * by other parts of the high level API
     *
     * @return RowRecord this row represents
     */

    protected RowRecord getRowRecord()
    {
        return row;
    }

    /**
     * used internally to refresh the "last cell plus one" when the last cell is removed.
     * @return 0 when row contains no cells
     */
    private int calculateNewLastCellPlusOne(int lastcell) {
        int cellIx = lastcell - 1;
        HSSFCell r = retrieveCell(cellIx);

        while (r == null) {
            if (cellIx < 0) {
                return 0;
            }
            r = retrieveCell(--cellIx);
        }
        return cellIx+1;
    }

    /**
     * used internally to refresh the "first cell" when the first cell is removed.
     * @return 0 when row contains no cells (also when first cell is occupied)
     */
    private int calculateNewFirstCell(int firstcell) {
        int cellIx = firstcell + 1;
        HSSFCell r = retrieveCell(cellIx);

        while (r == null) {
            if (cellIx <= cells.length) {
                return 0;
            }
            r = retrieveCell(++cellIx);
        }
        return cellIx;
    }

    /**
     * Is this row formatted? Most aren't, but some rows
     *  do have whole-row styles. For those that do, you
     *  can get the formatting from {@link #getRowStyle()}
     */
    @Override
    public boolean isFormatted() {
        return row.getFormatted();
    }
    /**
     * Returns the whole-row cell styles. Most rows won't
     *  have one of these, so will return null. Call
     *  {@link #isFormatted()} to check first.
     */
    @Override
    public HSSFCellStyle getRowStyle() {
        if(!isFormatted()) { return null; }
        short styleIndex = row.getXFIndex();
        ExtendedFormatRecord xf = book.getWorkbook().getExFormatAt(styleIndex);
        return new HSSFCellStyle(styleIndex, xf, book);
    }
    /**
     * Applies a whole-row cell styling to the row.
     */
    public void setRowStyle(HSSFCellStyle style) {
        row.setFormatted(true);
        row.setXFIndex(style.getIndex());
    }
    /**
     * Applies a whole-row cell styling to the row.
     */
    @Override
    public void setRowStyle(CellStyle style) {
        setRowStyle((HSSFCellStyle)style);
    }

    /**
     * @return cell iterator of the physically defined cells.
     * Note that the 4th element might well not be cell 4, as the iterator
     *  will not return un-defined (null) cells.
     * Call getCellNum() on the returned cells to know which cell they are.
     * As this only ever works on physically defined cells,
     *  the {@link org.apache.poi.ss.usermodel.Row.MissingCellPolicy} has no effect.
     */
    @Override
    public Iterator<Cell> cellIterator()
    {
      return new CellIterator();
    }
    /**
     * Alias for {@link #cellIterator} to allow
     *  foreach loops
     */
    @Override
    public Iterator<Cell> iterator() {
       return cellIterator();
    }

    /**
     * An iterator over the (physical) cells in the row.
     */
    private class CellIterator implements Iterator<Cell> {
      int thisId=-1;
      int nextId=-1;

      public CellIterator()
      {
        findNext();
      }

      @Override
    public boolean hasNext() {
        return nextId<cells.length;
      }

      @Override
    public Cell next() {
          if (!hasNext())
              throw new NoSuchElementException("At last element");
        HSSFCell cell=cells[nextId];
        thisId=nextId;
        findNext();
        return cell;
      }

      @Override
    public void remove() {
          if (thisId == -1)
              throw new IllegalStateException("remove() called before next()");
        cells[thisId]=null;
      }

      private void findNext()
      {
        int i=nextId+1;
        for(;i<cells.length;i++)
        {
          if(cells[i]!=null) break;
        }
        nextId=i;
      }

    }
    
    /**
     * Compares two <code>HSSFRow</code> objects.  Two rows are equal if they belong to the same worksheet and
     * their row indexes are equal.
     *
     * @param   other   the <code>HSSFRow</code> to be compared.
     * @return  <ul>
     *      <li>
     *      the value <code>0</code> if the row number of this <code>HSSFRow</code> is
     *      equal to the row number of the argument <code>HSSFRow</code>
     *      </li>
     *      <li>
     *      a value less than <code>0</code> if the row number of this this <code>HSSFRow</code> is
     *      numerically less than the row number of the argument <code>HSSFRow</code>
     *      </li>
     *      <li>
     *      a value greater than <code>0</code> if the row number of this this <code>HSSFRow</code> is
     *      numerically greater than the row number of the argument <code>HSSFRow</code>
     *      </li>
     *      </ul>
     * @throws IllegalArgumentException if the argument row belongs to a different worksheet
     */
    @Override
    public int compareTo(HSSFRow other)
    {
        if (this.getSheet() != other.getSheet()) {
            throw new IllegalArgumentException("The compared rows must belong to the same sheet");
        }

        Integer thisRow = this.getRowNum();
        Integer otherRow = other.getRowNum();
        return thisRow.compareTo(otherRow);
    }

    @Override
    public boolean equals(Object obj)
    {
        if (!(obj instanceof HSSFRow))
        {
            return false;
        }
        HSSFRow other = (HSSFRow) obj;

        return (this.getRowNum() == other.getRowNum()) &&
               (this.getSheet() == other.getSheet());
    }

    @Override
    public int hashCode() {
        return row.hashCode();
    }
}
