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

import static org.apache.poi.ooxml.POIXMLTypeLoader.DEFAULT_XML_OPTIONS;

import org.apache.poi.common.Duplicatable;
import org.apache.poi.ooxml.POIXMLException;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.FillPatternType;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.ReadingOrder;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.util.Internal;
import org.apache.poi.util.Removal;
import org.apache.poi.xssf.model.StylesTable;
import org.apache.poi.xssf.model.ThemesTable;
import org.apache.poi.xssf.usermodel.extensions.XSSFCellAlignment;
import org.apache.poi.xssf.usermodel.extensions.XSSFCellBorder;
import org.apache.poi.xssf.usermodel.extensions.XSSFCellBorder.BorderSide;
import org.apache.poi.xssf.usermodel.extensions.XSSFCellFill;
import org.apache.xmlbeans.XmlException;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBorder;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBorderPr;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCellAlignment;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTColor;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFill;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFont;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPatternFill;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTXf;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STBorderStyle;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STPatternType;

/**
 *
 * High level representation of the the possible formatting information for the contents of the cells on a sheet in a
 * SpreadsheetML document.
 *
 * @see org.apache.poi.xssf.usermodel.XSSFWorkbook#createCellStyle()
 * @see org.apache.poi.xssf.usermodel.XSSFWorkbook#getCellStyleAt(int)
 * @see org.apache.poi.xssf.usermodel.XSSFCell#setCellStyle(org.apache.poi.ss.usermodel.CellStyle)
 */
public class XSSFCellStyle implements CellStyle, Duplicatable {

    private int _cellXfId;
    private final StylesTable _stylesSource;
    private CTXf _cellXf;
    private final CTXf _cellStyleXf;
    private XSSFFont _font;
    private XSSFCellAlignment _cellAlignment;
    private ThemesTable _theme;

    /**
     * Creates a Cell Style from the supplied parts
     * @param cellXfId The main XF for the cell. Must be a valid 0-based index into the XF table
     * @param cellStyleXfId Optional, style xf. A value of <code>-1</code> means no xf.
     * @param stylesSource Styles Source to work off
     */
    public XSSFCellStyle(int cellXfId, int cellStyleXfId, StylesTable stylesSource, ThemesTable theme) {
        _cellXfId = cellXfId;
        _stylesSource = stylesSource;
        _cellXf = stylesSource.getCellXfAt(this._cellXfId);
        _cellStyleXf = cellStyleXfId == -1 ? null : stylesSource.getCellStyleXfAt(cellStyleXfId);
        _theme = theme;
    }

    /**
     * Used so that StylesSource can figure out our location
     */
    @Internal
    public CTXf getCoreXf() {
        return _cellXf;
    }

    /**
     * Used so that StylesSource can figure out our location
     */
    @Internal
    public CTXf getStyleXf() {
        return _cellStyleXf;
    }

    /**
     * Creates an empty Cell Style
     */
    public XSSFCellStyle(StylesTable stylesSource) {
        _stylesSource = stylesSource;
        // We need a new CTXf for the main styles
        // TODO decide on a style ctxf
        _cellXf = CTXf.Factory.newInstance();
        _cellStyleXf = null;
    }

    /**
     * Verifies that this style belongs to the supplied Workbook
     *  Styles Source.
     * Will throw an exception if it belongs to a different one.
     * This is normally called when trying to assign a style to a
     *  cell, to ensure the cell and the style are from the same
     *  workbook (if they're not, it won't work)
     * @throws IllegalArgumentException if there's a workbook mis-match
     */
    public void verifyBelongsToStylesSource(StylesTable src) {
        if(this._stylesSource != src) {
            throw new IllegalArgumentException("This Style does not belong to the supplied Workbook Styles Source. Are you trying to assign a style from one workbook to the cell of a different workbook?");
        }
    }

    /**
     * Clones all the style information from another
     *  XSSFCellStyle, onto this one. This
     *  XSSFCellStyle will then have all the same
     *  properties as the source, but the two may
     *  be edited independently.
     * Any stylings on this XSSFCellStyle will be lost!
     *
     * The source XSSFCellStyle could be from another
     *  XSSFWorkbook if you like. This allows you to
     *  copy styles from one XSSFWorkbook to another.
     */
    @Override
    public void cloneStyleFrom(CellStyle source) {
        if(source instanceof XSSFCellStyle) {
            XSSFCellStyle src = (XSSFCellStyle)source;

            // Is it on our Workbook?
            if(src._stylesSource == _stylesSource) {
               // Nice and easy
               _cellXf.set(src.getCoreXf());
               _cellStyleXf.set(src.getStyleXf());
            } else {
               // Copy the style
               try {
                  // Remove any children off the current style, to
                  //  avoid orphaned nodes
                  if(_cellXf.isSetAlignment())
                     _cellXf.unsetAlignment();
                  if(_cellXf.isSetExtLst())
                     _cellXf.unsetExtLst();

                  // Create a new Xf with the same contents
                  _cellXf = CTXf.Factory.parse(
                        src.getCoreXf().toString(), DEFAULT_XML_OPTIONS
                  );

                  // bug 56295: ensure that the fills is available and set correctly
                  CTFill fill = CTFill.Factory.parse(
                          src.getCTFill().toString(), DEFAULT_XML_OPTIONS
                          );
                  addFill(fill);

                  // bug 58084: set borders correctly
                  CTBorder border = CTBorder.Factory.parse(
                          src.getCTBorder().toString(), DEFAULT_XML_OPTIONS
                          );
                  addBorder(border);

                  // Swap it over
                  _stylesSource.replaceCellXfAt(_cellXfId, _cellXf);
               } catch(XmlException e) {
                  throw new POIXMLException(e);
               }

               // Copy the format
               String fmt = src.getDataFormatString();
               setDataFormat(
                     (new XSSFDataFormat(_stylesSource)).getFormat(fmt)
               );

               // Copy the font
               try {
                  CTFont ctFont = CTFont.Factory.parse(
                        src.getFont().getCTFont().toString(), DEFAULT_XML_OPTIONS
                  );
                  XSSFFont font = new XSSFFont(ctFont);
                  font.registerTo(_stylesSource);
                  setFont(font);
               } catch(XmlException e) {
                  throw new POIXMLException(e);
               }
            }

            // Clear out cached details
            _font = null;
            _cellAlignment = null;
        } else {
            throw new IllegalArgumentException("Can only clone from one XSSFCellStyle to another, not between HSSFCellStyle and XSSFCellStyle");
        }
    }

    private void addFill(CTFill fill) {
        int idx = _stylesSource.putFill(new XSSFCellFill(fill,_stylesSource.getIndexedColors()));

        _cellXf.setFillId(idx);
        _cellXf.setApplyFill(true);
    }

    private void addBorder(CTBorder border) {
        int idx = _stylesSource.putBorder(new XSSFCellBorder(border, _theme,_stylesSource.getIndexedColors()));

        _cellXf.setBorderId(idx);
        _cellXf.setApplyBorder(true);
    }

    @Override
    public HorizontalAlignment getAlignment() {
        CTCellAlignment align = _cellXf.getAlignment();
        if(align != null && align.isSetHorizontal()) {
            return HorizontalAlignment.forInt(align.getHorizontal().intValue()-1);
        }
        return HorizontalAlignment.GENERAL;
    }

    @Override
    public BorderStyle getBorderBottom() {
        if(!_cellXf.getApplyBorder()) return BorderStyle.NONE;

        int idx = Math.toIntExact(_cellXf.getBorderId());
        CTBorder ct = _stylesSource.getBorderAt(idx).getCTBorder();
        STBorderStyle.Enum ptrn = ct.isSetBottom() ? ct.getBottom().getStyle() : null;
        if (ptrn == null) {
            return BorderStyle.NONE;
        }
        return BorderStyle.valueOf((short)(ptrn.intValue() - 1));
    }

    @Override
    public BorderStyle getBorderLeft() {
        if(!_cellXf.getApplyBorder()) return BorderStyle.NONE;

        int idx = Math.toIntExact(_cellXf.getBorderId());
        CTBorder ct = _stylesSource.getBorderAt(idx).getCTBorder();
        STBorderStyle.Enum ptrn = ct.isSetLeft() ? ct.getLeft().getStyle() : null;
        if (ptrn == null) {
            return BorderStyle.NONE;
        }
        return BorderStyle.valueOf((short)(ptrn.intValue() - 1));
    }

    @Override
    public BorderStyle getBorderRight() {
        if(!_cellXf.getApplyBorder()) return BorderStyle.NONE;

        int idx = Math.toIntExact(_cellXf.getBorderId());
        CTBorder ct = _stylesSource.getBorderAt(idx).getCTBorder();
        STBorderStyle.Enum ptrn = ct.isSetRight() ? ct.getRight().getStyle() : null;
        if (ptrn == null) {
            return BorderStyle.NONE;
        }
        return BorderStyle.valueOf((short)(ptrn.intValue() - 1));
    }

    @Override
    public BorderStyle getBorderTop() {
        if(!_cellXf.getApplyBorder()) return BorderStyle.NONE;

        int idx = Math.toIntExact(_cellXf.getBorderId());
        CTBorder ct = _stylesSource.getBorderAt(idx).getCTBorder();
        STBorderStyle.Enum ptrn = ct.isSetTop() ? ct.getTop().getStyle() : null;
        if (ptrn == null) {
            return BorderStyle.NONE;
        }
        return BorderStyle.valueOf((short) (ptrn.intValue() - 1));
    }

    /**
     * Get the color to use for the bottom border
     * <br>
     * Color is optional. When missing, IndexedColors.AUTOMATIC is implied.
     * @return the index of the color definition, default value is {@link org.apache.poi.ss.usermodel.IndexedColors#AUTOMATIC}
     * @see org.apache.poi.ss.usermodel.IndexedColors
     */
    @Override
    public short getBottomBorderColor() {
        XSSFColor clr = getBottomBorderXSSFColor();
        return clr == null ? IndexedColors.BLACK.getIndex() : clr.getIndexed();
    }

    /**
     * Get the color to use for the bottom border as a {@link XSSFColor}
     *
     * @return the used color or <code>null</code> if not set
     */
    public XSSFColor getBottomBorderXSSFColor() {
        if(!_cellXf.getApplyBorder()) return null;

        int idx = Math.toIntExact(_cellXf.getBorderId());
        XSSFCellBorder border = _stylesSource.getBorderAt(idx);

        return border.getBorderColor(BorderSide.BOTTOM);
    }

    /**
     * Get the index of the number format (numFmt) record used by this cell format.
     *
     * @return the index of the number format
     */
    @Override
    public short getDataFormat() {
        return (short)_cellXf.getNumFmtId();
    }

    /**
     * Get the contents of the format string, by looking up
     * the StylesSource
     *
     * @return the number format string
     */
    @Override
    public String getDataFormatString() {
        int idx = getDataFormat();
        return new XSSFDataFormat(_stylesSource).getFormat((short)idx);
    }

    /**
     * Get the background fill color.
     * <p>
     * Note - many cells are actually filled with a foreground
     *  fill, not a background fill - see {@link #getFillForegroundColor()}
     * </p>
     * @return fill color, default value is {@link org.apache.poi.ss.usermodel.IndexedColors#AUTOMATIC}
     * @see org.apache.poi.ss.usermodel.IndexedColors
     */
    @Override
    public short getFillBackgroundColor() {
        XSSFColor clr = getFillBackgroundXSSFColor();
        return clr == null ? IndexedColors.AUTOMATIC.getIndex() : clr.getIndexed();
    }

    @Override
    public XSSFColor getFillBackgroundColorColor() {
       return getFillBackgroundXSSFColor();
    }

    /**
     * Get the background fill color.
     * <p>
     * Note - many cells are actually filled with a foreground
     *  fill, not a background fill - see {@link #getFillForegroundColor()}
     * </p>
     * @see org.apache.poi.xssf.usermodel.XSSFColor#getRGB()
     * @return XSSFColor - fill color or <code>null</code> if not set
     */
    public XSSFColor getFillBackgroundXSSFColor() {
        // bug 56295: handle missing applyFill attribute as "true" because Excel does as well
        if(_cellXf.isSetApplyFill() && !_cellXf.getApplyFill()) return null;

        int fillIndex = (int)_cellXf.getFillId();
        XSSFCellFill fg = _stylesSource.getFillAt(fillIndex);

        XSSFColor fillBackgroundColor = fg.getFillBackgroundColor();
        if (fillBackgroundColor != null && _theme != null) {
            _theme.inheritFromThemeAsRequired(fillBackgroundColor);
        }
        return fillBackgroundColor;
    }

    /**
     * Get the foreground fill color.
     * <p>
     * Many cells are filled with this, instead of a
     *  background color ({@link #getFillBackgroundColor()})
     * </p>
     * @see IndexedColors
     * @return fill color, default value is {@link org.apache.poi.ss.usermodel.IndexedColors#AUTOMATIC}
     */
    @Override
    public short getFillForegroundColor() {
        XSSFColor clr = getFillForegroundXSSFColor();
        return clr == null ? IndexedColors.AUTOMATIC.getIndex() : clr.getIndexed();
    }

    @Override
    public XSSFColor getFillForegroundColorColor() {
       return getFillForegroundXSSFColor();
    }

    /**
     * Get the foreground fill color.
     *
     * @return XSSFColor - fill color or <code>null</code> if not set
     */
    public XSSFColor getFillForegroundXSSFColor() {
        // bug 56295: handle missing applyFill attribute as "true" because Excel does as well
        if(_cellXf.isSetApplyFill() && !_cellXf.getApplyFill()) return null;

        int fillIndex = (int)_cellXf.getFillId();
        XSSFCellFill fg = _stylesSource.getFillAt(fillIndex);

        XSSFColor fillForegroundColor = fg.getFillForegroundColor();
        if (fillForegroundColor != null && _theme != null) {
            _theme.inheritFromThemeAsRequired(fillForegroundColor);
        }
        return fillForegroundColor;
    }

    @Override
    public FillPatternType getFillPattern() {
        // bug 56295: handle missing applyFill attribute as "true" because Excel does as well
        if(_cellXf.isSetApplyFill() && !_cellXf.getApplyFill()) return FillPatternType.NO_FILL;

        int fillIndex = (int)_cellXf.getFillId();
        XSSFCellFill fill = _stylesSource.getFillAt(fillIndex);

        STPatternType.Enum ptrn = fill.getPatternType();
        if(ptrn == null) return FillPatternType.NO_FILL;
        return FillPatternType.forInt(ptrn.intValue() - 1);
    }

    /**
     * Gets the font for this style
     * @return Font - font
     */
    public XSSFFont getFont() {
        if (_font == null) {
            _font = _stylesSource.getFontAt(getFontId());
        }
        return _font;
    }

    /**
     * Gets the index of the font for this style
     *
     * @return font index
     * @see org.apache.poi.xssf.usermodel.XSSFWorkbook#getFontAt(int)
     * @since 5.0.0 (used to return a short value)
     */
    @Override
    public int getFontIndex() {
        return getFontId();
    }

    /**
     * Gets the index of the font for this style
     *
     * @return font index
     * @see org.apache.poi.xssf.usermodel.XSSFWorkbook#getFontAt(int)
     * @deprecated use {@link #getFontIndex()} instead
     * @since 4.0.0
     */
    @Deprecated
    @Removal(version = "6.0.0")
    @Override
    public int getFontIndexAsInt() {
        return getFontId();
    }

    /**
     * Get whether the cell's using this style are to be hidden
     *
     * @return boolean -  whether the cell using this style is hidden
     */
    @Override
    public boolean getHidden() {
        return _cellXf.isSetProtection() && _cellXf.getProtection().isSetHidden() && _cellXf.getProtection().getHidden();
    }

    /**
     * Get the number of spaces to indent the text in the cell
     *
     * @return indent - number of spaces
     */
    @Override
    public short getIndention() {
        CTCellAlignment align = _cellXf.getAlignment();
        return (short)(align == null ? 0 : align.getIndent());
    }

    /**
     * Get the index within the StylesTable (sequence within the collection of CTXf elements)
     *
     * @return unique index number of the underlying record this style represents, as a short (may wrap)
     */
    @Override
    public short getIndex() {
        return (short)this._cellXfId;
    }

    /**
     * Workaround for places where we need to support more than 32767 cell styles, ideally
     * the main getIndex() and others would return int, not short, but that would affect some
     * public APIs
     *
     * @return unique index number of the underlying record this style represents, as an int (always positive)
     */
    protected int getUIndex() {
        return this._cellXfId;
    }

    /**
     * Get the color to use for the left border
     *
     * @return the index of the color definition, default value is {@link org.apache.poi.ss.usermodel.IndexedColors#BLACK}
     * @see org.apache.poi.ss.usermodel.IndexedColors
     */
    @Override
    public short getLeftBorderColor() {
        XSSFColor clr = getLeftBorderXSSFColor();
        return clr == null ? IndexedColors.BLACK.getIndex() : clr.getIndexed();
    }

    /**
     * Get the color to use for the left border
     *
     * @return the index of the color definition or <code>null</code> if not set
     * @see org.apache.poi.ss.usermodel.IndexedColors
     */
    public XSSFColor getLeftBorderXSSFColor() {
        if(!_cellXf.getApplyBorder()) return null;

        int idx = Math.toIntExact(_cellXf.getBorderId());
        XSSFCellBorder border = _stylesSource.getBorderAt(idx);

        return border.getBorderColor(BorderSide.LEFT);
    }

    /**
     * Get whether the cell's using this style are locked
     *
     * @return whether the cell using this style are locked
     */
    @Override
    public boolean getLocked() {
        return !_cellXf.isSetProtection() || !_cellXf.getProtection().isSetLocked() || _cellXf.getProtection().getLocked();
    }

    /**
     * Is "Quote Prefix" or "123 Prefix" enabled for the cell?
     */
    @Override
    public boolean getQuotePrefixed() {
        return _cellXf.getQuotePrefix();
    }

    /**
     * Get the color to use for the right border
     *
     * @return the index of the color definition, default value is {@link org.apache.poi.ss.usermodel.IndexedColors#BLACK}
     * @see org.apache.poi.ss.usermodel.IndexedColors
     */
    @Override
    public short getRightBorderColor() {
        XSSFColor clr = getRightBorderXSSFColor();
        return clr == null ? IndexedColors.BLACK.getIndex() : clr.getIndexed();
    }
    /**
     * Get the color to use for the right border
     *
     * @return the used color or <code>null</code> if not set
     */
    public XSSFColor getRightBorderXSSFColor() {
        if(!_cellXf.getApplyBorder()) return null;

        int idx = Math.toIntExact(_cellXf.getBorderId());
        XSSFCellBorder border = _stylesSource.getBorderAt(idx);

        return border.getBorderColor(BorderSide.RIGHT);
    }

    /**
     * Get the degree of rotation for the text in the cell
     * <p>
     * Expressed in degrees. Values range from 0 to 180. The first letter of
     * the text is considered the center-point of the arc.
     * <br>
     * For 0 - 90, the value represents degrees above horizon. For 91-180 the degrees below the
     * horizon is calculated as:
     * <br>
     * <code>[degrees below horizon] = 90 - textRotation.</code>
     * </p>
     *
     * @return rotation degrees (between 0 and 180 degrees)
     */
    @Override
    public short getRotation() {
        CTCellAlignment align = _cellXf.getAlignment();
        return align == null || align.getTextRotation() == null ? 0 : align.getTextRotation().shortValue();
    }

    @Override
    public boolean getShrinkToFit() {
        CTCellAlignment align = _cellXf.getAlignment();
        return align != null && align.getShrinkToFit();
    }

    /**
     * Get the color to use for the top border
     *
     * @return the index of the color definition, default value is {@link org.apache.poi.ss.usermodel.IndexedColors#BLACK}
     * @see org.apache.poi.ss.usermodel.IndexedColors
     */
    @Override
    public short getTopBorderColor() {
        XSSFColor clr = getTopBorderXSSFColor();
        return clr == null ? IndexedColors.BLACK.getIndex() : clr.getIndexed();
    }

    /**
     * Get the color to use for the top border
     *
     * @return the used color or <code>null</code> if not set
     */
    public XSSFColor getTopBorderXSSFColor() {
        if(!_cellXf.getApplyBorder()) return null;

        int idx = Math.toIntExact(_cellXf.getBorderId());
        XSSFCellBorder border = _stylesSource.getBorderAt(idx);

        return border.getBorderColor(BorderSide.TOP);
    }

    @Override
    public VerticalAlignment getVerticalAlignment() {
        CTCellAlignment align = _cellXf.getAlignment();
        if(align != null && align.isSetVertical()) {
            return VerticalAlignment.forInt(align.getVertical().intValue()-1);
        }
        return VerticalAlignment.BOTTOM;
    }

    /**
     * Whether the text should be wrapped
     *
     * @return  a boolean value indicating if the text in a cell should be line-wrapped within the cell.
     */
    @Override
    public boolean getWrapText() {
        CTCellAlignment align = _cellXf.getAlignment();
        return align != null && align.getWrapText();
    }

    /**
     * Set the type of horizontal alignment for the cell
     *
     * @param align - the type of alignment
     */
    @Override
    public void setAlignment(HorizontalAlignment align) {
        getCellAlignment().setHorizontal(align);
    }

    /**
     * Set the type of border to use for the bottom border of the cell
     *
     * @param border - type of border to use
     * @see org.apache.poi.ss.usermodel.BorderStyle
     * @since POI 3.15
     */
    @Override
    public void setBorderBottom(BorderStyle border) {
        CTBorder ct = getCTBorder();
        CTBorderPr pr = ct.isSetBottom() ? ct.getBottom() : ct.addNewBottom();
        if(border == BorderStyle.NONE) ct.unsetBottom();
        else pr.setStyle(STBorderStyle.Enum.forInt(border.getCode() + 1));

        int idx = _stylesSource.putBorder(new XSSFCellBorder(ct, _theme, _stylesSource.getIndexedColors()));

        _cellXf.setBorderId(idx);
        _cellXf.setApplyBorder(true);
    }

     /**
     * Set the type of border to use for the left border of the cell
      *
     * @param border the type of border to use
     * @since POI 3.15
     */
    @Override
    public void setBorderLeft(BorderStyle border) {
        CTBorder ct = getCTBorder();
        CTBorderPr pr = ct.isSetLeft() ? ct.getLeft() : ct.addNewLeft();
        if(border == BorderStyle.NONE) ct.unsetLeft();
        else pr.setStyle(STBorderStyle.Enum.forInt(border.getCode() + 1));

        int idx = _stylesSource.putBorder(new XSSFCellBorder(ct, _theme, _stylesSource.getIndexedColors()));

        _cellXf.setBorderId(idx);
        _cellXf.setApplyBorder(true);
    }

     /**
     * Set the type of border to use for the right border of the cell
      *
     * @param border the type of border to use
     * @since POI 3.15
     */
    @Override
    public void setBorderRight(BorderStyle border) {
        CTBorder ct = getCTBorder();
        CTBorderPr pr = ct.isSetRight() ? ct.getRight() : ct.addNewRight();
        if(border == BorderStyle.NONE) ct.unsetRight();
        else pr.setStyle(STBorderStyle.Enum.forInt(border.getCode() + 1));

        int idx = _stylesSource.putBorder(new XSSFCellBorder(ct, _theme,_stylesSource.getIndexedColors()));

        _cellXf.setBorderId(idx);
        _cellXf.setApplyBorder(true);
    }

    /**
     * Set the type of border to use for the top border of the cell
     *
     * @param border the type of border to use
     * @since POI 3.15
     */
    @Override
    public void setBorderTop(BorderStyle border) {
        CTBorder ct = getCTBorder();
        CTBorderPr pr = ct.isSetTop() ? ct.getTop() : ct.addNewTop();
        if(border == BorderStyle.NONE) ct.unsetTop();
        else pr.setStyle(STBorderStyle.Enum.forInt(border.getCode() + 1));

        int idx = _stylesSource.putBorder(new XSSFCellBorder(ct, _theme,_stylesSource.getIndexedColors()));

        _cellXf.setBorderId(idx);
        _cellXf.setApplyBorder(true);
    }

    /**
     * Set the color to use for the bottom border
     * @param color the index of the color definition
     * @see org.apache.poi.ss.usermodel.IndexedColors
     */
    @Override
    public void setBottomBorderColor(short color) {
        XSSFColor clr = XSSFColor.from(CTColor.Factory.newInstance(), _stylesSource.getIndexedColors());
        clr.setIndexed(color);
        setBottomBorderColor(clr);
    }

    /**
     * Set the color to use for the bottom border
     *
     * @param color the color to use, null means no color
     */
    public void setBottomBorderColor(XSSFColor color) {
        CTBorder ct = getCTBorder();
        if(color == null && !ct.isSetBottom()) return;

        CTBorderPr pr = ct.isSetBottom() ? ct.getBottom() : ct.addNewBottom();
        if(color != null)  pr.setColor(color.getCTColor());
        else pr.unsetColor();

        int idx = _stylesSource.putBorder(new XSSFCellBorder(ct, _theme,_stylesSource.getIndexedColors()));

        _cellXf.setBorderId(idx);
        _cellXf.setApplyBorder(true);
    }

    /**
     * Set the index of a data format
     *
     * @param fmt the index of a data format
     */
    @Override
    public void setDataFormat(short fmt) {
        // XSSF supports >32,767 formats
        setDataFormat(fmt&0xffff);
    }
    /**
     * Set the index of a data format
     *
     * @param fmt the index of a data format
     */
    public void setDataFormat(int fmt) {
        _cellXf.setApplyNumberFormat(true);
        _cellXf.setNumFmtId(fmt);
    }

    /**
     * Set the background fill color represented as a {@link XSSFColor} value.
     * <p>
     * For example:
     * <pre>
     * cs.setFillPattern(XSSFCellStyle.FINE_DOTS );
     * cs.setFillBackgroundXSSFColor(new XSSFColor(java.awt.Color.RED));
     * </pre>
     * optionally a Foreground and background fill can be applied:
     * <i>Note: Ensure Foreground color is set prior to background</i>
     * <pre>
     * cs.setFillPattern(XSSFCellStyle.FINE_DOTS );
     * cs.setFillForegroundColor(new XSSFColor(java.awt.Color.BLUE));
     * cs.setFillBackgroundColor(new XSSFColor(java.awt.Color.GREEN));
     * </pre>
     * or, for the special case of SOLID_FILL:
     * <pre>
     * cs.setFillPattern(XSSFCellStyle.SOLID_FOREGROUND );
     * cs.setFillForegroundColor(new XSSFColor(java.awt.Color.GREEN));
     * </pre>
     * It is necessary to set the fill style in order
     * for the color to be shown in the cell.
     *
     * @param color - the color to use
     */
    public void setFillBackgroundColor(XSSFColor color) {
        CTFill ct = getCTFill();
        CTPatternFill ptrn = ct.getPatternFill();
        if(color == null) {
            if(ptrn != null && ptrn.isSetBgColor()) ptrn.unsetBgColor();
        } else {
            if(ptrn == null) ptrn = ct.addNewPatternFill();
            ptrn.setBgColor(color.getCTColor());
        }

        addFill(ct);
    }

    /**
     * Set the background fill color represented as a indexed color value.
     * <p>
     * For example:
     * <pre>
     * cs.setFillPattern(XSSFCellStyle.FINE_DOTS );
     * cs.setFillBackgroundXSSFColor(IndexedColors.RED.getIndex());
     * </pre>
     * optionally a Foreground and background fill can be applied:
     * <i>Note: Ensure Foreground color is set prior to background</i>
     * <pre>
     * cs.setFillPattern(XSSFCellStyle.FINE_DOTS );
     * cs.setFillForegroundColor(IndexedColors.BLUE.getIndex());
     * cs.setFillBackgroundColor(IndexedColors.RED.getIndex());
     * </pre>
     * or, for the special case of SOLID_FILL:
     * <pre>
     * cs.setFillPattern(XSSFCellStyle.SOLID_FOREGROUND );
     * cs.setFillForegroundColor(IndexedColors.RED.getIndex());
     * </pre>
     * It is necessary to set the fill style in order
     * for the color to be shown in the cell.
     *
     * @param bg - the color to use
     * @see org.apache.poi.ss.usermodel.IndexedColors
     */
    @Override
    public void setFillBackgroundColor(short bg) {
        XSSFColor clr = XSSFColor.from(CTColor.Factory.newInstance(), _stylesSource.getIndexedColors());
        clr.setIndexed(bg);
        setFillBackgroundColor(clr);
    }

    /**
    * Set the foreground fill color represented as a {@link XSSFColor} value.
     * <br>
    * <i>Note: Ensure Foreground color is set prior to background color.</i>
    * @param color the color to use
    * @see #setFillBackgroundColor(org.apache.poi.xssf.usermodel.XSSFColor) )
    */
    public void setFillForegroundColor(XSSFColor color) {
        CTFill ct = getCTFill();

        CTPatternFill ptrn = ct.getPatternFill();
        if(color == null) {
            if(ptrn != null && ptrn.isSetFgColor()) ptrn.unsetFgColor();
        } else {
            if(ptrn == null) ptrn = ct.addNewPatternFill();
            ptrn.setFgColor(color.getCTColor());
        }

        addFill(ct);
    }

    /**
     * Set the foreground fill color as a indexed color value
     * <br>
     * <i>Note: Ensure Foreground color is set prior to background color.</i>
     * @param fg the color to use
     * @see org.apache.poi.ss.usermodel.IndexedColors
     */
    @Override
    public void setFillForegroundColor(short fg) {
        XSSFColor clr = XSSFColor.from(CTColor.Factory.newInstance(), _stylesSource.getIndexedColors());
        clr.setIndexed(fg);
        setFillForegroundColor(clr);
    }

    /**
     * Get a <b>copy</b> of the currently used CTFill, if none is used, return a new instance.
     */
    private CTFill getCTFill(){
        CTFill ct;
        // bug 56295: handle missing applyFill attribute as "true" because Excel does as well
        if(!_cellXf.isSetApplyFill() || _cellXf.getApplyFill()) {
            int fillIndex = (int)_cellXf.getFillId();
            XSSFCellFill cf = _stylesSource.getFillAt(fillIndex);

            ct = (CTFill)cf.getCTFill().copy();
        } else {
            ct = CTFill.Factory.newInstance();
        }
        return ct;
    }

    /**
     * Set reading order for the cell
     *
     * @param order - the reading order
     */
    public void setReadingOrder(ReadingOrder order) {
        getCellAlignment().setReadingOrder(order);
    }

    /**
     * Get reading order of the cell
     *
     * @return ReadingOrder - the reading order
     */
    public ReadingOrder getReadingOrder() {
        return getCellAlignment().getReadingOrder();
    }

    /**
     * Get a <b>copy</b> of the currently used CTBorder, if none is used, return a new instance.
     */
    private CTBorder getCTBorder(){
        CTBorder ct;
        if(_cellXf.getApplyBorder()) {
            int idx = Math.toIntExact(_cellXf.getBorderId());
            XSSFCellBorder cf = _stylesSource.getBorderAt(idx);

            ct = (CTBorder)cf.getCTBorder().copy();
        } else {
            ct = CTBorder.Factory.newInstance();
        }
        return ct;
    }

    /**
     * This element is used to specify cell fill information for pattern and solid color cell fills. For solid cell fills (no pattern),
     * foreground color is used is used. For cell fills with patterns specified, then the cell fill color is specified by the background color element.
     *
     * @param pattern the fill pattern to use
     * @see #setFillBackgroundColor(XSSFColor)
     * @see #setFillForegroundColor(XSSFColor)
     * @see org.apache.poi.ss.usermodel.FillPatternType
     */
    @Override
    public void setFillPattern(FillPatternType pattern) {
        CTFill ct = getCTFill();
        CTPatternFill ctptrn = ct.isSetPatternFill() ? ct.getPatternFill() : ct.addNewPatternFill();
        if (pattern == FillPatternType.NO_FILL && ctptrn.isSetPatternType()) {
            ctptrn.unsetPatternType();
        } else {
            ctptrn.setPatternType(STPatternType.Enum.forInt(pattern.getCode() + 1));
        }

        addFill(ct);
    }

    /**
     * Set the font for this style
     *
     * @param font  a font object created or retrieved from the XSSFWorkbook object
     * @see org.apache.poi.xssf.usermodel.XSSFWorkbook#createFont()
     * @see org.apache.poi.xssf.usermodel.XSSFWorkbook#getFontAt(short)
     */
    @Override
    public void setFont(Font font) {
        if(font != null){
            long index = font.getIndexAsInt();
            this._cellXf.setFontId(index);
            this._cellXf.setApplyFont(true);
        } else {
            this._cellXf.setApplyFont(false);
        }
    }

    /**
     * Set the cell's using this style to be hidden
     *
     * @param hidden - whether the cell using this style should be hidden
     */
    @Override
    public void setHidden(boolean hidden) {
        if (!_cellXf.isSetProtection()) {
             _cellXf.addNewProtection();
         }
        _cellXf.getProtection().setHidden(hidden);
    }

    /**
     * Set the number of spaces to indent the text in the cell
     *
     * @param indent - number of spaces
     */
    @Override
    public void setIndention(short indent) {
        getCellAlignment().setIndent(indent);
    }

    /**
     * Set the color to use for the left border as a indexed color value
     *
     * @param color the index of the color definition
     * @see org.apache.poi.ss.usermodel.IndexedColors
     */
    @Override
    public void setLeftBorderColor(short color) {
        XSSFColor clr = XSSFColor.from(CTColor.Factory.newInstance(), _stylesSource.getIndexedColors());
        clr.setIndexed(color);
        setLeftBorderColor(clr);
    }

    /**
     * Set the color to use for the left border as a {@link XSSFColor} value
     *
     * @param color the color to use
     */
    public void setLeftBorderColor(XSSFColor color) {
        CTBorder ct = getCTBorder();
        if(color == null && !ct.isSetLeft()) return;

        CTBorderPr pr = ct.isSetLeft() ? ct.getLeft() : ct.addNewLeft();
        if(color != null)  pr.setColor(color.getCTColor());
        else pr.unsetColor();

        int idx = _stylesSource.putBorder(new XSSFCellBorder(ct, _theme,_stylesSource.getIndexedColors()));

        _cellXf.setBorderId(idx);
        _cellXf.setApplyBorder(true);
    }

    /**
     * Set the cell's using this style to be locked
     *
     * @param locked -  whether the cell using this style should be locked
     */
    @Override
    public void setLocked(boolean locked) {
        if (!_cellXf.isSetProtection()) {
             _cellXf.addNewProtection();
         }
        _cellXf.getProtection().setLocked(locked);
    }

    /**
     * Turn on or off "Quote Prefix" or "123 Prefix" for the style,
     *  which is used to tell Excel that the thing which looks like
     *  a number or a formula shouldn't be treated as on.
     */
    @Override
    public void setQuotePrefixed(boolean quotePrefix) {
        _cellXf.setQuotePrefix(quotePrefix);
    }

    /**
     * Set the color to use for the right border
     *
     * @param color the index of the color definition
     * @see org.apache.poi.ss.usermodel.IndexedColors
     */
    @Override
    public void setRightBorderColor(short color) {
        XSSFColor clr = XSSFColor.from(CTColor.Factory.newInstance(), _stylesSource.getIndexedColors());
        clr.setIndexed(color);
        setRightBorderColor(clr);
    }

    /**
     * Set the color to use for the right border as a {@link XSSFColor} value
     *
     * @param color the color to use
     */
    public void setRightBorderColor(XSSFColor color) {
        CTBorder ct = getCTBorder();
        if(color == null && !ct.isSetRight()) return;

        CTBorderPr pr = ct.isSetRight() ? ct.getRight() : ct.addNewRight();
        if(color != null)  pr.setColor(color.getCTColor());
        else pr.unsetColor();

        int idx = _stylesSource.putBorder(new XSSFCellBorder(ct, _theme,_stylesSource.getIndexedColors()));

        _cellXf.setBorderId(idx);
        _cellXf.setApplyBorder(true);
    }

    /**
     * Set the degree of rotation for the text in the cell
     * <p>
     * Expressed in degrees. Values range from 0 to 180. The first letter of
     * the text is considered the center-point of the arc.
     * <br>
     * For 0 - 90, the value represents degrees above horizon. For 91-180 the degrees below the
     * horizon is calculated as:
     * <br>
     * <code>[degrees below horizon] = 90 - textRotation.</code>
     * </p>
     *
     * Note: HSSF uses values from -90 to 90 degrees, whereas XSSF
     * uses values from 0 to 180 degrees. The implementations of this method will map between these two value-ranges
     * accordingly, however the corresponding getter is returning values in the range mandated by the current type
     * of Excel file-format that this CellStyle is applied to.
     *
     * @param rotation - the rotation degrees (between 0 and 180 degrees)
     */
    @Override
    public void setRotation(short rotation) {
        getCellAlignment().setTextRotation(rotation);
    }


    /**
     * Set the color to use for the top border
     *
     * @param color the index of the color definition
     * @see org.apache.poi.ss.usermodel.IndexedColors
     */
    @Override
    public void setTopBorderColor(short color) {
        XSSFColor clr = XSSFColor.from(CTColor.Factory.newInstance(), _stylesSource.getIndexedColors());
        clr.setIndexed(color);
        setTopBorderColor(clr);
    }

    /**
     * Set the color to use for the top border as a {@link XSSFColor} value
     *
     * @param color the color to use
     */
    public void setTopBorderColor(XSSFColor color) {
        CTBorder ct = getCTBorder();
        if(color == null && !ct.isSetTop()) return;

        CTBorderPr pr = ct.isSetTop() ? ct.getTop() : ct.addNewTop();
        if(color != null)  pr.setColor(color.getCTColor());
        else pr.unsetColor();

        int idx = _stylesSource.putBorder(new XSSFCellBorder(ct, _theme,_stylesSource.getIndexedColors()));

        _cellXf.setBorderId(idx);
        _cellXf.setApplyBorder(true);
    }

    /**
     * Set the type of vertical alignment for the cell
     *
     * @param align - the type of alignment
     */
    public void setVerticalAlignment(VerticalAlignment align) {
        getCellAlignment().setVertical(align);
    }

    /**
     * Set whether the text should be wrapped.
     * <p>
     * Setting this flag to <code>true</code> make all content visible
     * whithin a cell by displaying it on multiple lines
     * </p>
     *
     * @param wrapped a boolean value indicating if the text in a cell should be line-wrapped within the cell.
     */
    @Override
    public void setWrapText(boolean wrapped) {
        getCellAlignment().setWrapText(wrapped);
    }

    /**
     * Gets border color
     *
     * @param side the border side
     * @return the used color
     */
    public XSSFColor getBorderColor(BorderSide side) {
        switch(side){
            case BOTTOM:
                return getBottomBorderXSSFColor();
            case RIGHT:
                return getRightBorderXSSFColor();
            case TOP:
                return getTopBorderXSSFColor();
            case LEFT:
                return getLeftBorderXSSFColor();
            default:
                throw new IllegalArgumentException("Unknown border: " + side);
        }
    }

    /**
     * Set the color to use for the selected border
     *
     * @param side - where to apply the color definition
     * @param color - the color to use
     */
    public void setBorderColor(BorderSide side, XSSFColor color) {
        switch(side){
            case BOTTOM:
                setBottomBorderColor(color);
                break;
            case RIGHT:
                setRightBorderColor(color);
                break;
            case TOP:
                setTopBorderColor(color);
                break;
            case LEFT:
                setLeftBorderColor(color);
                break;
        }
    }

    @Override
    public void setShrinkToFit(boolean shrinkToFit) {
        getCellAlignment().setShrinkToFit(shrinkToFit);
    }

    private int getFontId() {
        if (_cellXf.isSetFontId()) {
            return (int) _cellXf.getFontId();
        }
        return (int) _cellStyleXf.getFontId();
    }

    /**
     * get the cellAlignment object to use for manage alignment
     * @return XSSFCellAlignment - cell alignment
     */
    protected XSSFCellAlignment getCellAlignment() {
        if (this._cellAlignment == null) {
            this._cellAlignment = new XSSFCellAlignment(getCTCellAlignment());
        }
        return this._cellAlignment;
    }

    /**
     * Return the CTCellAlignment instance for alignment
     *
     * @return CTCellAlignment
     */
    private CTCellAlignment getCTCellAlignment() {
        if (_cellXf.getAlignment() == null) {
            _cellXf.setAlignment(CTCellAlignment.Factory.newInstance());
        }
        return _cellXf.getAlignment();
    }

    /**
     * Returns a hash code value for the object. The hash is derived from the underlying CTXf bean.
     *
     * @return the hash code value for this style
     */
    @Override
    public int hashCode(){
        return _cellXf.toString().hashCode();
    }

    /**
     * Checks is the supplied style is equal to this style
     *
     * @param o the style to check
     * @return true if the supplied style is equal to this style
     */
    @Override
    public boolean equals(Object o){
        if(o == null || !(o instanceof XSSFCellStyle)) return false;

        XSSFCellStyle cf = (XSSFCellStyle)o;
        return _cellXf.toString().equals(cf.getCoreXf().toString());
    }

    /**
     * Make a copy of this style. The underlying CTXf bean is cloned,
     * the references to fills and borders remain.
     *
     * @return a copy of this style
     */
    @Override
    public XSSFCellStyle copy(){
        CTXf xf = (CTXf)_cellXf.copy();

        int xfSize = _stylesSource._getStyleXfsSize();
        int indexXf = _stylesSource.putCellXf(xf);
        return new XSSFCellStyle(indexXf-1, xfSize-1, _stylesSource, _theme);
    }
}
