/* FichothequeLib_Tools - Copyright (c) 2015-2024 Vincent Calame - Exemole
 * Logiciel libre donné sous triple licence :
 * 1) selon les termes de la CeCILL V2
 * 2) selon les termes de l’EUPL V.1.1
 * 3) selon les termes de la GNU GPLv3
 * Voir le fichier licences.txt
 */


package net.fichotheque.tools.exportation.table;

import java.io.IOException;
import java.util.Collection;
import java.util.List;
import net.fichotheque.Subset;
import net.fichotheque.SubsetItem;
import net.fichotheque.exportation.table.ColDef;
import net.fichotheque.exportation.table.SubsetTable;
import net.fichotheque.exportation.table.TableExportConstants;
import net.fichotheque.utils.TableDefUtils;
import net.mapeadores.opendocument.io.odtable.OdColumnDef;
import net.mapeadores.opendocument.io.odtable.OdsXMLPart;
import net.mapeadores.opendocument.io.odtable.StyleManager;
import net.mapeadores.util.exceptions.NestedIOException;
import net.mapeadores.util.localisation.Lang;
import net.mapeadores.util.money.Amount;
import net.mapeadores.util.primitives.Decimal;
import net.mapeadores.util.primitives.FuzzyDate;
import net.mapeadores.util.table.TableWriter;
import net.mapeadores.util.xml.XMLWriter;
import net.fichotheque.exportation.table.SumCellConverter;
import net.fichotheque.exportation.table.SumResult;


/**
 *
 * @author Vincent Calame
 */
public class SubsetTableOdsXMLPart extends OdsXMLPart {

    private final static String COLUMNHEADER_STYLE = "ColumnHeader";
    private final static String TITLE_STYLE = "Title";
    private final TableExportOdsParameters tableExportOdsParameters;


    public SubsetTableOdsXMLPart(XMLWriter xmlWriter, StyleManager styleManager, TableExportOdsParameters tableExportOdsParameters) {
        super(xmlWriter, styleManager);
        this.tableExportOdsParameters = tableExportOdsParameters;
    }

    public int addSubsetTable(String tableName, SubsetTable subsetTable, Collection<SubsetItem> subsetItems, int startRowNumber, NamedRangeHandler namedRangeHandler) throws IOException {
        Subset subset = subsetTable.getSubset();
        int rowCount = 0;
        switch (tableExportOdsParameters.getHeaderType()) {
            case TableExportConstants.COLUMNTITLE_HEADER:
                printHeaderTitle(subsetTable.getColDefList(), tableExportOdsParameters.getWorkingLang(), subset);
                startRowNumber++;
                rowCount++;
                break;
            case TableExportConstants.COLUMNKEY_HEADER:
                printHeaderKey(subsetTable.getColDefList());
                startRowNumber++;
                rowCount++;
                break;

        }
        InternalTableWriter tableWriter = new InternalTableWriter(tableName, startRowNumber, new FormulaEngine(subsetTable));
        try {
            SumCellConverter sumCellConverter = tableExportOdsParameters.getSumCellConverter();
            TableExportEngine.exportSubset(subsetTable, tableWriter, tableExportOdsParameters.getSumCellConverter(), subsetItems);
            SumResult sumResult = sumCellConverter.getSumResult(subsetTable);
            rowCount = rowCount + tableWriter.rowCount;
            namedRangeHandler.setCurrentSubset(subset.getSubsetKey());
            rowCount = rowCount + TableExportEngine.writeSumRows(tableWriter, sumResult, tableWriter.rowNumber + 1, namedRangeHandler);
        } catch (NestedIOException nioe) {
            throw nioe.getIOException();
        }
        return rowCount;
    }

    public int addTitleRows(String title) throws IOException {
        this
                .rowStart()
                .stringCell(title, TITLE_STYLE)
                .rowEnd()
                .rowStart()
                .rowEnd();
        return 2;
    }


    private void printHeaderTitle(List<ColDef> colDefList, Lang workingLang, Subset subset) throws IOException {
        rowStart();
        for (ColDef colDef : colDefList) {
            stringCell(TableDefUtils.getColTitle(colDef, workingLang, tableExportOdsParameters.getTableExportContext().getSourceLabelProvider(), subset), COLUMNHEADER_STYLE, 1);
        }
        rowEnd();
    }

    private void printHeaderKey(List<ColDef> colDefList) throws IOException {
        rowStart();
        for (ColDef colDef : colDefList) {
            stringCell(colDef.getColName(), COLUMNHEADER_STYLE, 1);
        }
        rowEnd();
    }


    private class InternalTableWriter implements TableWriter {

        private final String tableName;
        private final FormulaEngine formulaEngine;
        private int rowNumber;
        private int rowCount;
        private int columnNumber;

        private InternalTableWriter(String tableName, int startRowNumber, FormulaEngine formulaEngine) {
            this.tableName = tableName;
            this.rowNumber = startRowNumber - 1;
            this.rowCount = 0;
            this.formulaEngine = formulaEngine;
        }

        @Override
        public int startRow() {
            rowNumber++;
            rowCount++;
            columnNumber = 0;
            try {
                rowStart();
            } catch (IOException ioe) {
                throw new NestedIOException(ioe);
            }
            return rowNumber;
        }

        @Override
        public int addIntegerCell(Long lg) {
            columnNumber++;
            try {
                if (lg == null) {
                    emptyCell();
                } else {
                    numberCell(lg.toString());
                }
            } catch (IOException ioe) {
                throw new NestedIOException(ioe);
            }
            return columnNumber;
        }

        @Override
        public int addDecimalCell(Decimal decimal) {
            columnNumber++;
            try {
                if (decimal == null) {
                    emptyCell();
                } else {
                    numberCell(decimal.toString());
                }
            } catch (IOException ioe) {
                throw new NestedIOException(ioe);
            }
            return columnNumber;
        }

        @Override
        public int addDateCell(FuzzyDate date) {
            columnNumber++;
            try {
                if (date == null) {
                    emptyCell();
                } else {
                    String cellStyleName = getCellStyleName(tableName, columnNumber, OdColumnDef.DATE_STYLE_FAMILY, null);
                    dateCell(date, cellStyleName);
                }
            } catch (IOException ioe) {
                throw new NestedIOException(ioe);
            }
            return columnNumber;
        }

        @Override
        public int addStringCell(String s) {
            columnNumber++;
            try {
                if (s == null) {
                    emptyCell();
                } else {
                    if (formulaEngine.isFormulaColumn(columnNumber)) {
                        formulaEngine.writeFormulaCell(rowNumber, columnNumber, SubsetTableOdsXMLPart.this, s);
                    } else {
                        stringCell(s);
                    }
                }
            } catch (IOException ioe) {
                throw new NestedIOException(ioe);
            }
            return columnNumber;
        }

        @Override
        public int addMoneyCell(Amount amount) {
            columnNumber++;
            try {
                if (amount == null) {
                    emptyCell();
                } else {
                    String cellStyleName = getCurrencyStyleName(tableName, columnNumber, null, amount.getCurrency());
                    currencyCell(amount, cellStyleName);
                }
            } catch (IOException ioe) {
                throw new NestedIOException(ioe);
            }
            return columnNumber;
        }

        @Override
        public int addPercentageCell(Decimal decimal) {
            columnNumber++;
            try {
                if (decimal == null) {
                    emptyCell();
                } else {
                    percentageCell(decimal.toString());
                }
            } catch (IOException ioe) {
                throw new NestedIOException(ioe);
            }
            return columnNumber;
        }

        @Override
        public int endRow() {
            try {
                rowEnd();
            } catch (IOException ioe) {
                throw new NestedIOException(ioe);
            }
            return rowNumber;
        }

    }

}
