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

import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackageRelationship;
import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.usermodel.BuiltinFormats;
import org.apache.poi.ss.usermodel.FontFamily;
import org.apache.poi.ss.usermodel.FontScheme;
import org.apache.poi.util.Internal;
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.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.CTBorder;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBorders;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCellStyleXfs;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCellXfs;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDxf;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDxfs;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFill;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFills;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFont;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTFonts;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTNumFmt;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTNumFmts;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTStylesheet;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTXf;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STPatternType;
import org.openxmlformats.schemas.spreadsheetml.x2006.main.StyleSheetDocument;

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

    private final List<CTDxf> dxfs = new ArrayList<CTDxf>();

    /**
     * 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());
    }

    /**
     * @deprecated in POI 3.14, scheduled for removal in POI 3.16
     */
    @Deprecated
    public StylesTable(PackagePart part, PackageRelationship rel) throws IOException {
        this(part);
    }
    
    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;

        // 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;

        theme = (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.
     */
    protected 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
            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);
                    fonts.add(f);
                    idx++;
                }
            }
            CTFills ctfills = styleSheet.getFills();
            if(ctfills != null){
                for (CTFill fill : ctfills.getFillArray()) {
                    fills.add(new XSSFCellFill(fill));
                }
            }

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

            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()));

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

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

    /**
     * Get number format string given its id
     * 
     * @param idx number format id
     * @return number format code
     * @deprecated POI 3.14-beta2. Use {@link #getNumberFormatAt(short)} instead.
     */
    public String getNumberFormatAt(int idx) {
        return getNumberFormatAt((short) idx);
    }
    
    /**
     * Get number format string given its id
     * 
     * @param fmtId number format id
     * @return number format code
     */
    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.
     */
    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
     */
    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
     */
    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
     */
    public boolean removeNumberFormat(String fmt) {
        short id = getNumberFormatId(fmt);
        return removeNumberFormat(id);
    }

    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)}
     */
    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;
    }
    public int putFont(XSSFFont font) {
        return putFont(font, false);
    }

    public XSSFCellStyle getStyleAt(int idx) {
        int styleXfId = 0;

        // 0 is the empty default
        if(xfs.get(idx).getXfId() > 0) {
            styleXfId = (int) xfs.get(idx).getXfId();
        }

        return new XSSFCellStyle(idx, styleXfId, this, theme);
    }
    public int putStyle(XSSFCellStyle style) {
        CTXf mainXF = style.getCoreXf();

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

    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
     */
    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;
    }

    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
     */
    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
     */
    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
     */
    public int getNumDataFormats() {
        return numberFormats.size();
    }
    
    /**
     * For unit testing only
     * @deprecated POI 3.14 beta 2. Use {@link #getNumDataFormats()} instead.
     */
    @Internal
    public int _getNumberFormatSize() {
        return getNumDataFormats();
    }

    /**
     * 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[xfs.size()])
            );
            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[styleXfs.size()])
            );
            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[dxfs.size()]));
            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]));
        fills.add(new XSSFCellFill(ctFill[1]));

        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);
        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();
    }

    /**
     * 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
     * @deprecated POI 3.15 beta 2. Use {@link #findFont(boolean, short, short, String, boolean, boolean, short, byte)} instead.
     */
    public XSSFFont findFont(short boldWeight, short color, short fontHeight, String name, boolean italic, boolean strikeout, short typeOffset, byte underline) {
        for (XSSFFont font : fonts) {
            if (	(font.getBoldweight() == boldWeight)
                    && 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
     */
    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;
    }
}
