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

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

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;

import org.apache.poi.ooxml.POIXMLDocumentPart;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.util.Internal;
import org.apache.poi.xssf.usermodel.CustomIndexedColorMap;
import org.apache.poi.xssf.usermodel.DefaultIndexedColorMap;
import org.apache.poi.xssf.usermodel.IndexedColorMap;
import org.apache.poi.xssf.usermodel.XSSFBuiltinTableStyle;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFFactory;
import org.apache.poi.xssf.usermodel.XSSFFont;
import org.apache.poi.xssf.usermodel.XSSFRelation;
import org.apache.poi.xssf.usermodel.XSSFTableStyle;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xssf.usermodel.extensions.XSSFCellBorder;
import org.apache.poi.xssf.usermodel.extensions.XSSFCellFill;
import org.apache.xmlbeans.XmlException;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.*;

/**
 * Table of styles shared across all sheets in a workbook.
 */
public class StylesTable extends POIXMLDocumentPart implements Styles {
    private final SortedMap<Short, String> numberFormats = new TreeMap<>();
    private final List<XSSFFont> fonts = new ArrayList<>();
    private final List<XSSFCellFill> fills = new ArrayList<>();
    private final List<XSSFCellBorder> borders = new ArrayList<>();
    private final List<CTXf> styleXfs = new ArrayList<>();
    private final List<CTXf> xfs = new ArrayList<>();

    private final List<CTDxf> dxfs = new ArrayList<>();
    private final Map<String, TableStyle> tableStyles = new HashMap<>();

    private IndexedColorMap indexedColors = new DefaultIndexedColorMap();

    /**
     * The first style id available for use as a custom style
     */
    public static final int FIRST_CUSTOM_STYLE_ID = BuiltinFormats.FIRST_USER_DEFINED_FORMAT_INDEX + 1;
    // Is this right? Number formats (XSSFDataFormat) and cell styles (XSSFCellStyle) are different. What's up with the plus 1?
    private static final int MAXIMUM_STYLE_ID = SpreadsheetVersion.EXCEL2007.getMaxCellStyles();

    private static final short FIRST_USER_DEFINED_NUMBER_FORMAT_ID = BuiltinFormats.FIRST_USER_DEFINED_FORMAT_INDEX;
    /**
     * Depending on the version of Excel, the maximum number of number formats in a workbook is between 200 and 250
     * See https://support.office.com/en-us/article/excel-specifications-and-limits-1672b34d-7043-467e-8e27-269d656771c3
     * POI defaults this limit to 250, but can be increased or decreased on a per-StylesTable basis with
     * {@link #setMaxNumberOfDataFormats(int)} if needed.
     */
    private int MAXIMUM_NUMBER_OF_DATA_FORMATS = 250;

    /**
     * Changes the maximum number of data formats that may be in a style table
     *
     * @param num the upper limit on number of data formats in the styles table when adding new data formats
     * @throws IllegalArgumentException if <code>num</code> < 0
     * @throws IllegalStateException if <code>num</code> < current number of data formats in the style table.
     * Data formats must be explicitly removed before the limit can be decreased.
     */
    public void setMaxNumberOfDataFormats(int num) {
        if (num < getNumDataFormats()) {
            if (num < 0) {
                throw new IllegalArgumentException("Maximum Number of Data Formats must be greater than or equal to 0");
            } else {
                throw new IllegalStateException("Cannot set the maximum number of data formats less than the current quantity. " +
                        "Data formats must be explicitly removed (via StylesTable.removeNumberFormat) before the limit can be decreased.");
            }
        }
        MAXIMUM_NUMBER_OF_DATA_FORMATS = num;
    }

    /**
     * Get the upper limit on the number of data formats that has been set for the style table.
     * To get the current number of data formats in use, use {@link #getNumDataFormats()}.
     *
     * @return the maximum number of data formats allowed in the workbook
     */
    public int getMaxNumberOfDataFormats() {
        return MAXIMUM_NUMBER_OF_DATA_FORMATS;
    }

    private StyleSheetDocument doc;
    private XSSFWorkbook workbook;
    private ThemesTable theme;

    /**
     * Create a new, empty StylesTable
     */
    public StylesTable() {
        super();
        doc = StyleSheetDocument.Factory.newInstance();
        doc.addNewStyleSheet();
        // Initialization required in order to make the document readable by MSExcel
        initialize();
    }

    /**
     * @since POI 3.14-Beta1
     */
    public StylesTable(PackagePart part) throws IOException {
        super(part);
        readFrom(part.getInputStream());
    }

    public void setWorkbook(XSSFWorkbook wb) {
        this.workbook = wb;
    }

    /**
     * Get the current Workbook's theme table, or null if the
     *  Workbook lacks any themes.
     * <p>Use {@link #ensureThemesTable()} to have a themes table
     *  created if needed
     */
    public ThemesTable getTheme() {
        return theme;
    }

    public void setTheme(ThemesTable theme) {
        this.theme = theme;

        if (theme != null) theme.setColorMap(getIndexedColors());

        // Pass the themes table along to things which need to
        //  know about it, but have already been created by now
        for(XSSFFont font : fonts) {
            font.setThemesTable(theme);
        }
        for(XSSFCellBorder border : borders) {
            border.setThemesTable(theme);
        }
    }

    /**
     * If there isn't currently a {@link ThemesTable} for the
     *  current Workbook, then creates one and sets it up.
     * After this, calls to {@link #getTheme()} won't give null
     */
    public void ensureThemesTable() {
        if (theme != null) return;

        setTheme((ThemesTable)workbook.createRelationship(XSSFRelation.THEME, XSSFFactory.getInstance()));
    }

    /**
     * Read this shared styles table from an XML file.
     *
     * @param is The input stream containing the XML document.
     * @throws IOException if an error occurs while reading.
     */
    public void readFrom(InputStream is) throws IOException {
        try {
            doc = StyleSheetDocument.Factory.parse(is, DEFAULT_XML_OPTIONS);

            CTStylesheet styleSheet = doc.getStyleSheet();

            // Grab all the different bits we care about

            // keep this first, as some constructors below want it
            IndexedColorMap customColors = CustomIndexedColorMap.fromColors(styleSheet.getColors());
            if (customColors != null) indexedColors = customColors;

            CTNumFmts ctfmts = styleSheet.getNumFmts();
            if( ctfmts != null){
                for (CTNumFmt nfmt : ctfmts.getNumFmtArray()) {
                    short formatId = (short)nfmt.getNumFmtId();
                    numberFormats.put(formatId, nfmt.getFormatCode());
                }
            }

            CTFonts ctfonts = styleSheet.getFonts();
            if(ctfonts != null){
                int idx = 0;
                for (CTFont font : ctfonts.getFontArray()) {
                    // Create the font and save it. Themes Table supplied later
                    XSSFFont f = new XSSFFont(font, idx, indexedColors);
                    fonts.add(f);
                    idx++;
                }
            }
            CTFills ctfills = styleSheet.getFills();
            if(ctfills != null){
                for (CTFill fill : ctfills.getFillArray()) {
                    fills.add(new XSSFCellFill(fill, indexedColors));
                }
            }

            CTBorders ctborders = styleSheet.getBorders();
            if(ctborders != null) {
                for (CTBorder border : ctborders.getBorderArray()) {
                    borders.add(new XSSFCellBorder(border, indexedColors));
                }
            }

            CTCellXfs cellXfs = styleSheet.getCellXfs();
            if(cellXfs != null) xfs.addAll(Arrays.asList(cellXfs.getXfArray()));

            CTCellStyleXfs cellStyleXfs = styleSheet.getCellStyleXfs();
            if(cellStyleXfs != null) styleXfs.addAll(Arrays.asList(cellStyleXfs.getXfArray()));

            CTDxfs styleDxfs = styleSheet.getDxfs();
            if(styleDxfs != null) dxfs.addAll(Arrays.asList(styleDxfs.getDxfArray()));

            CTTableStyles ctTableStyles = styleSheet.getTableStyles();
            if (ctTableStyles != null && styleDxfs != null) {
                int idx = 0;
                for (CTTableStyle style : ctTableStyles.getTableStyleArray()) {
                    tableStyles.put(style.getName(), new XSSFTableStyle(idx, styleDxfs, style, indexedColors));
                    idx++;
                }
            }

        } catch (XmlException e) {
            throw new IOException(e.getLocalizedMessage());
        }
    }

    // ===========================================================
    //  Start of style related getters and setters
    // ===========================================================

    /**
     * Get number format string given its id
     *
     * @param fmtId number format id
     * @return number format code
     */
    @Override
    public String getNumberFormatAt(short fmtId) {
        return numberFormats.get(fmtId);
    }

    private short getNumberFormatId(String fmt) {
        // Find the key, and return that
        for (Entry<Short,String> numFmt : numberFormats.entrySet()) {
            if(numFmt.getValue().equals(fmt)) {
                return numFmt.getKey();
            }
        }
        throw new IllegalStateException("Number format not in style table: " + fmt);
    }

    /**
     * Puts <code>fmt</code> in the numberFormats map if the format is not
     * already in the the number format style table.
     * Does nothing if <code>fmt</code> is already in number format style table.
     *
     * @param fmt the number format to add to number format style table
     * @return the index of <code>fmt</code> in the number format style table
     * @throws IllegalStateException if adding the number format to the styles table
     * would exceed the {@link #MAXIMUM_NUMBER_OF_DATA_FORMATS} allowed.
     */
    @Override
    public int putNumberFormat(String fmt) {
        // Check if number format already exists
        if (numberFormats.containsValue(fmt)) {
            try {
                return getNumberFormatId(fmt);
            } catch (final IllegalStateException e) {
                throw new IllegalStateException("Found the format, but couldn't figure out where - should never happen!");
            }
        }


        if (numberFormats.size() >= MAXIMUM_NUMBER_OF_DATA_FORMATS) {
            throw new IllegalStateException("The maximum number of Data Formats was exceeded. " +
                    "You can define up to " + MAXIMUM_NUMBER_OF_DATA_FORMATS + " formats in a .xlsx Workbook.");
        }

        // Find a spare key, and add that
        final short formatIndex;
        if (numberFormats.isEmpty()) {
            formatIndex = FIRST_USER_DEFINED_NUMBER_FORMAT_ID;
        }
        else {
            // get next-available numberFormat index.
            // Assumption: gaps in number format ids are acceptable
            // to catch arithmetic overflow, nextKey's data type
            // must match numberFormat's key data type
            short nextKey = (short) (numberFormats.lastKey() + 1);
            if (nextKey < 0) {
                throw new IllegalStateException(
                        "Cowardly avoiding creating a number format with a negative id. " +
                        "This is probably due to arithmetic overflow.");
            }
            formatIndex = (short) Math.max(nextKey, FIRST_USER_DEFINED_NUMBER_FORMAT_ID);
        }

        numberFormats.put(formatIndex, fmt);
        return formatIndex;
    }


    /**
     * Add a number format with a specific ID into the numberFormats map.
     * If a format with the same ID already exists, overwrite the format code
     * with <code>fmt</code>
     * This may be used to override built-in number formats.
     *
     * @param index the number format ID
     * @param fmt the number format code
     */
    @Override
    public void putNumberFormat(short index, String fmt) {
        numberFormats.put(index, fmt);
    }

    /**
     * Remove a number format from the style table if it exists.
     * All cell styles with this number format will be modified to use the default number format.
     *
     * @param index the number format id to remove
     * @return true if the number format was removed
     */
    @Override
    public boolean removeNumberFormat(short index) {
        String fmt = numberFormats.remove(index);
        boolean removed = (fmt != null);
        if (removed) {
            for (final CTXf style : xfs) {
                if (style.isSetNumFmtId() && style.getNumFmtId() == index) {
                    style.unsetApplyNumberFormat();
                    style.unsetNumFmtId();
                }
            }
        }
        return removed;
    }

    /**
     * Remove a number format from the style table if it exists
     * All cell styles with this number format will be modified to use the default number format
     *
     * @param fmt the number format to remove
     * @return true if the number format was removed
     */
    @Override
    public boolean removeNumberFormat(String fmt) {
        short id = getNumberFormatId(fmt);
        return removeNumberFormat(id);
    }

    @Override
    public XSSFFont getFontAt(int idx) {
        return fonts.get(idx);
    }

    /**
     * Records the given font in the font table.
     * Will re-use an existing font index if this
     *  font matches another, EXCEPT if forced
     *  registration is requested.
     * This allows people to create several fonts
     *  then customise them later.
     * Note - End Users probably want to call
     *  {@link XSSFFont#registerTo(StylesTable)}
     */
    @Override
    public int putFont(XSSFFont font, boolean forceRegistration) {
        int idx = -1;
        if(!forceRegistration) {
            idx = fonts.indexOf(font);
        }

        if (idx != -1) {
            return idx;
        }

        idx = fonts.size();
        fonts.add(font);
        return idx;
    }

    @Override
    public int putFont(XSSFFont font) {
        return putFont(font, false);
    }

    /**
     *
     * @param idx style index
     * @return XSSFCellStyle or null if idx is out of bounds for xfs array
     */
    @Override
    public XSSFCellStyle getStyleAt(int idx) {
        int styleXfId = 0;

        if (idx < 0 || idx >= xfs.size()) {
            //BUG-60343
            return null;
        }
        // 0 is the empty default
        if(xfs.get(idx).getXfId() > 0) {
            styleXfId = (int) xfs.get(idx).getXfId();
        }

        return new XSSFCellStyle(idx, styleXfId, this, theme);
    }

    @Override
    public int putStyle(XSSFCellStyle style) {
        CTXf mainXF = style.getCoreXf();

        if(! xfs.contains(mainXF)) {
            xfs.add(mainXF);
        }
        return xfs.indexOf(mainXF);
    }

    @Override
    public XSSFCellBorder getBorderAt(int idx) {
        return borders.get(idx);
    }

    /**
     * Adds a border to the border style table if it isn't already in the style table
     * Does nothing if border is already in borders style table
     *
     * @param border border to add
     * @return the index of the added border
     */
    @Override
    public int putBorder(XSSFCellBorder border) {
        int idx = borders.indexOf(border);
        if (idx != -1) {
            return idx;
        }
        borders.add(border);
        border.setThemesTable(theme);
        return borders.size() - 1;
    }

    @Override
    public XSSFCellFill getFillAt(int idx) {
        return fills.get(idx);
    }

    public List<XSSFCellBorder> getBorders(){
        return Collections.unmodifiableList(borders);
    }

    public List<XSSFCellFill> getFills(){
        return Collections.unmodifiableList(fills);
    }

    public List<XSSFFont> getFonts(){
        return Collections.unmodifiableList(fonts);
    }

    public Map<Short, String> getNumberFormats(){
        return Collections.unmodifiableMap(numberFormats);
    }

    /**
     * Adds a fill to the fill style table if it isn't already in the style table
     * Does nothing if fill is already in fill style table
     *
     * @param fill fill to add
     * @return the index of the added fill
     */
    @Override
    public int putFill(XSSFCellFill fill) {
        int idx = fills.indexOf(fill);
        if (idx != -1) {
            return idx;
        }
        fills.add(fill);
        return fills.size() - 1;
    }

    @Internal
    public CTXf getCellXfAt(int idx) {
        return xfs.get(idx);
    }

    /**
     * Adds a cell to the styles table.
     * Does not check for duplicates.
     *
     * @param cellXf the cell to add to the styles table
     * @return the added cell ID in the style table
     */
    @Internal
    public int putCellXf(CTXf cellXf) {
        xfs.add(cellXf);
        return xfs.size();
    }

    @Internal
    public void replaceCellXfAt(int idx, CTXf cellXf) {
        xfs.set(idx, cellXf);
    }

    @Internal
    public CTXf getCellStyleXfAt(int idx) {
        try {
            return styleXfs.get(idx);
        }
        catch (final IndexOutOfBoundsException e) {
            return null;
        }
    }

    /**
     * Adds a cell style to the styles table.
     * Does not check for duplicates.
     *
     * @param cellStyleXf the cell style to add to the styles table
     * @return the cell style ID in the style table
     */
    @Internal
    public int putCellStyleXf(CTXf cellStyleXf) {
        styleXfs.add(cellStyleXf);
        // TODO: check for duplicate
        return styleXfs.size();
    }

    @Internal
    protected void replaceCellStyleXfAt(int idx, CTXf cellStyleXf) {
        styleXfs.set(idx, cellStyleXf);
    }

    /**
     * get the size of cell styles
     */
    @Override
    public int getNumCellStyles() {
        // Each cell style has a unique xfs entry
        // Several might share the same styleXfs entry
        return xfs.size();
    }

    /**
     * @return number of data formats in the styles table
     */
    @Override
    public int getNumDataFormats() {
        return numberFormats.size();
    }

    /**
     * For unit testing only
     */
    @Internal
    /*package*/ int _getXfsSize() {
        return xfs.size();
    }
    /**
     * For unit testing only
     */
    @Internal
    public int _getStyleXfsSize() {
        return styleXfs.size();
    }

    /**
     * For unit testing only!
     */
    @Internal
    public CTStylesheet getCTStylesheet() {
        return doc.getStyleSheet();
    }

    @Internal
    public int _getDXfsSize() {
        return dxfs.size();
    }


    /**
     * Write this table out as XML.
     *
     * @param out The stream to write to.
     * @throws IOException if an error occurs while writing.
     */
    public void writeTo(OutputStream out) throws IOException {
        // Work on the current one
        // Need to do this, as we don't handle
        //  all the possible entries yet
        CTStylesheet styleSheet = doc.getStyleSheet();

        // Formats
        CTNumFmts formats = CTNumFmts.Factory.newInstance();
        formats.setCount(numberFormats.size());
        for (final Entry<Short, String> entry : numberFormats.entrySet()) {
            CTNumFmt ctFmt = formats.addNewNumFmt();
            ctFmt.setNumFmtId(entry.getKey());
            ctFmt.setFormatCode(entry.getValue());
        }
        styleSheet.setNumFmts(formats);

        int idx;
        // Fonts
        CTFonts ctFonts = styleSheet.getFonts();
        if (ctFonts == null) {
            ctFonts = CTFonts.Factory.newInstance();
        }
        ctFonts.setCount(fonts.size());
        CTFont[] ctfnt = new CTFont[fonts.size()];
        idx = 0;
        for(XSSFFont f : fonts) ctfnt[idx++] = f.getCTFont();
        ctFonts.setFontArray(ctfnt);
        styleSheet.setFonts(ctFonts);

        // Fills
        CTFills ctFills = styleSheet.getFills();
        if (ctFills == null) {
            ctFills = CTFills.Factory.newInstance();
        }
        ctFills.setCount(fills.size());
        CTFill[] ctf = new CTFill[fills.size()];
        idx = 0;
        for(XSSFCellFill f : fills) ctf[idx++] = f.getCTFill();
        ctFills.setFillArray(ctf);
        styleSheet.setFills(ctFills);

        // Borders
        CTBorders ctBorders = styleSheet.getBorders();
        if (ctBorders == null) {
            ctBorders = CTBorders.Factory.newInstance();
        }
        ctBorders.setCount(borders.size());
        CTBorder[] ctb = new CTBorder[borders.size()];
        idx = 0;
        for(XSSFCellBorder b : borders) ctb[idx++] = b.getCTBorder();
        ctBorders.setBorderArray(ctb);
        styleSheet.setBorders(ctBorders);

        // Xfs
        if(xfs.size() > 0) {
            CTCellXfs ctXfs = styleSheet.getCellXfs();
            if (ctXfs == null) {
                ctXfs = CTCellXfs.Factory.newInstance();
            }
            ctXfs.setCount(xfs.size());
            ctXfs.setXfArray(
                    xfs.toArray(new CTXf[0])
            );
            styleSheet.setCellXfs(ctXfs);
        }

        // Style xfs
        if(styleXfs.size() > 0) {
            CTCellStyleXfs ctSXfs = styleSheet.getCellStyleXfs();
            if (ctSXfs == null) {
                ctSXfs = CTCellStyleXfs.Factory.newInstance();
            }
            ctSXfs.setCount(styleXfs.size());
            ctSXfs.setXfArray(
                    styleXfs.toArray(new CTXf[0])
            );
            styleSheet.setCellStyleXfs(ctSXfs);
        }

        // Style dxfs
        if(dxfs.size() > 0) {
            CTDxfs ctDxfs = styleSheet.getDxfs();
            if (ctDxfs == null) {
                ctDxfs = CTDxfs.Factory.newInstance();
            }
            ctDxfs.setCount(dxfs.size());
            ctDxfs.setDxfArray(dxfs.toArray(new CTDxf[0]));
            styleSheet.setDxfs(ctDxfs);
        }

        // Save
        doc.save(out, DEFAULT_XML_OPTIONS);
    }

    @Override
    protected void commit() throws IOException {
        PackagePart part = getPackagePart();
        OutputStream out = part.getOutputStream();
        writeTo(out);
        out.close();
    }

    private void initialize() {
        //CTFont ctFont = createDefaultFont();
        XSSFFont xssfFont = createDefaultFont();
        fonts.add(xssfFont);

        CTFill[] ctFill = createDefaultFills();
        fills.add(new XSSFCellFill(ctFill[0], indexedColors));
        fills.add(new XSSFCellFill(ctFill[1], indexedColors));

        CTBorder ctBorder = createDefaultBorder();
        borders.add(new XSSFCellBorder(ctBorder));

        CTXf styleXf = createDefaultXf();
        styleXfs.add(styleXf);
        CTXf xf = createDefaultXf();
        xf.setXfId(0);
        xfs.add(xf);
    }

    private static CTXf createDefaultXf() {
        CTXf ctXf = CTXf.Factory.newInstance();
        ctXf.setNumFmtId(0);
        ctXf.setFontId(0);
        ctXf.setFillId(0);
        ctXf.setBorderId(0);
        return ctXf;
    }
    private static CTBorder createDefaultBorder() {
        CTBorder ctBorder = CTBorder.Factory.newInstance();
        ctBorder.addNewBottom();
        ctBorder.addNewTop();
        ctBorder.addNewLeft();
        ctBorder.addNewRight();
        ctBorder.addNewDiagonal();
        return ctBorder;
    }


    private static CTFill[] createDefaultFills() {
        CTFill[] ctFill = new CTFill[]{CTFill.Factory.newInstance(),CTFill.Factory.newInstance()};
        ctFill[0].addNewPatternFill().setPatternType(STPatternType.NONE);
        ctFill[1].addNewPatternFill().setPatternType(STPatternType.DARK_GRAY);
        return ctFill;
    }

    private static XSSFFont createDefaultFont() {
        CTFont ctFont = CTFont.Factory.newInstance();
        XSSFFont xssfFont=new XSSFFont(ctFont, 0, null);
        xssfFont.setFontHeightInPoints(XSSFFont.DEFAULT_FONT_SIZE);
        xssfFont.setColor(XSSFFont.DEFAULT_FONT_COLOR);//setTheme
        xssfFont.setFontName(XSSFFont.DEFAULT_FONT_NAME);
        xssfFont.setFamily(FontFamily.SWISS);
        xssfFont.setScheme(FontScheme.MINOR);
        return xssfFont;
    }

    @Internal
    public CTDxf getDxfAt(int idx) {
        return dxfs.get(idx);
    }

    /**
     * Adds a Dxf to the style table
     * Does not check for duplicates.
     *
     * @param dxf the Dxf to add
     * @return added dxf ID in the style table
     */
    @Internal
    public int putDxf(CTDxf dxf) {
        this.dxfs.add(dxf);
        return this.dxfs.size();
    }

    /**
     * NOTE: this only returns explicitly defined styles
     * @param name of the table style
     * @return defined style, or null if not explicitly defined
     *
     * @since 3.17 beta 1
     */
    public TableStyle getExplicitTableStyle(String name) {
        return tableStyles.get(name);
    }

    /**
     * @return names of all explicitly defined table styles in the workbook
     * @since 3.17 beta 1
     */
    public Set<String> getExplicitTableStyleNames() {
        return tableStyles.keySet();
    }

    /**
     * @param name of the table style
     * @return defined style, either explicit or built-in, or null if not found
     *
     * @since 3.17 beta 1
     */
    public TableStyle getTableStyle(String name) {
        if (name == null) return null;
        try {
            return XSSFBuiltinTableStyle.valueOf(name).getStyle();
        } catch (IllegalArgumentException e) {
            return getExplicitTableStyle(name);
        }
    }

    /**
     * Create a cell style in this style table.
     * Note - End users probably want to call {@link XSSFWorkbook#createCellStyle()}
     * rather than working with the styles table directly.
     * @throws IllegalStateException if the maximum number of cell styles has been reached.
     */
    public XSSFCellStyle createCellStyle() {
        if (getNumCellStyles() > MAXIMUM_STYLE_ID) {
            throw new IllegalStateException("The maximum number of Cell Styles was exceeded. " +
                      "You can define up to " + MAXIMUM_STYLE_ID + " style in a .xlsx Workbook");
        }

        int xfSize = styleXfs.size();
        CTXf xf = CTXf.Factory.newInstance();
        xf.setNumFmtId(0);
        xf.setFontId(0);
        xf.setFillId(0);
        xf.setBorderId(0);
        xf.setXfId(0);
        int indexXf = putCellXf(xf);
        return new XSSFCellStyle(indexXf - 1, xfSize - 1, this, theme);
    }

    /**
     * Finds a font that matches the one with the supplied attributes,
     * where color is the indexed-value, not the actual color.
     */
    public XSSFFont findFont(boolean bold, short color, short fontHeight, String name, boolean italic, boolean strikeout, short typeOffset, byte underline) {
        for (XSSFFont font : fonts) {
            if (    (font.getBold() == bold)
                    && font.getColor() == color
                    && font.getFontHeight() == fontHeight
                    && font.getFontName().equals(name)
                    && font.getItalic() == italic
                    && font.getStrikeout() == strikeout
                    && font.getTypeOffset() == typeOffset
                    && font.getUnderline() == underline)
            {
                return font;
            }
        }
        return null;
    }

    /**
     * Finds a font that matches the one with the supplied attributes,
     * where color is the actual Color-value, not the indexed color
     */
    public XSSFFont findFont(boolean bold, Color color, short fontHeight, String name, boolean italic, boolean strikeout, short typeOffset, byte underline) {
        for (XSSFFont font : fonts) {
            if (    (font.getBold() == bold)
                    && font.getXSSFColor().equals(color)
                    && font.getFontHeight() == fontHeight
                    && font.getFontName().equals(name)
                    && font.getItalic() == italic
                    && font.getStrikeout() == strikeout
                    && font.getTypeOffset() == typeOffset
                    && font.getUnderline() == underline)
            {
                return font;
            }
        }
        return null;
    }

    /**
     * @return default or custom indexed color to RGB mapping
     */
    public IndexedColorMap getIndexedColors() {
        return indexedColors;
    }
}
