/* OdLib_Io - Copyright (c) 2013-2020 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.mapeadores.opendocument.io.odtable;

import java.util.AbstractList;
import java.util.ArrayList;
import java.util.List;
import java.util.RandomAccess;
import net.mapeadores.util.money.ExtendedCurrency;


/**
 *
 * @author Vincent Calame
 */
public class OdTableDefBuilder {

    private final static OdColumnDef STANDARD_COLUMNDEF = new InternalOdColumnDef(OdColumnDef.STANDARD_STYLE_FAMILY, null, null, null);
    private final static OdColumnDef DATE_COLUMNDEF = new InternalOdColumnDef(OdColumnDef.DATE_STYLE_FAMILY, null, null, null);
    private final List<OdColumnDef> odColumnList = new ArrayList<OdColumnDef>();
    private final String tableName;

    public OdTableDefBuilder(String tableName) {
        this.tableName = tableName;
    }

    public OdTableDefBuilder addStandard() {
        odColumnList.add(STANDARD_COLUMNDEF);
        return this;
    }

    public OdTableDefBuilder addStandard(String customStyleName) {
        odColumnList.add(new InternalOdColumnDef(OdColumnDef.STANDARD_STYLE_FAMILY, null, customStyleName, null));
        return this;
    }

    public OdTableDefBuilder addStandard(String customStyleName, String defaulCellStyleName) {
        odColumnList.add(new InternalOdColumnDef(OdColumnDef.STANDARD_STYLE_FAMILY, null, customStyleName, defaulCellStyleName));
        return this;
    }

    public OdTableDefBuilder addStandards(int length) {
        for (int i = 0; i < length; i++) {
            odColumnList.add(STANDARD_COLUMNDEF);
        }
        return this;
    }

    public OdTableDefBuilder addStandards(int length, String customStyleName) {
        OdColumnDef columnDef = new InternalOdColumnDef(OdColumnDef.STANDARD_STYLE_FAMILY, null, customStyleName, null);
        for (int i = 0; i < length; i++) {
            odColumnList.add(columnDef);
        }
        return this;
    }

    public OdTableDefBuilder addStandards(int length, String customStyleName, String defaulCellStyleName) {
        OdColumnDef columnDef = new InternalOdColumnDef(OdColumnDef.STANDARD_STYLE_FAMILY, null, customStyleName, defaulCellStyleName);
        for (int i = 0; i < length; i++) {
            odColumnList.add(columnDef);
        }
        return this;
    }

    public OdTableDefBuilder addDate() {
        odColumnList.add(DATE_COLUMNDEF);
        return this;
    }

    public OdTableDefBuilder addCurrency(ExtendedCurrency currency) {
        odColumnList.add(new InternalOdColumnDef(OdColumnDef.CURRENCY_STYLE_FAMILY, currency, null, null));
        return this;
    }

    public OdTableDefBuilder add(OdColumnDef odColumnDef) {
        odColumnList.add(odColumnDef);
        return this;
    }

    public OdTableDef toOdTableDef() {
        OdColumnDef[] odColumnArray = odColumnList.toArray(new OdColumnDef[odColumnList.size()]);
        return new InternalOdTableDef(tableName, wrap(odColumnArray));
    }

    public static OdTableDefBuilder init(String tableName) {
        return new OdTableDefBuilder(tableName);
    }

    public static OdTableDef buildStandard(String tableName, int colCount) {
        OdColumnDef[] odColumnArray = new OdColumnDef[colCount];
        for (int i = 0; i < colCount; i++) {
            odColumnArray[i] = STANDARD_COLUMNDEF;
        }
        return new InternalOdTableDef(tableName, wrap(odColumnArray));
    }


    private static class InternalOdTableDef implements OdTableDef {

        private final String tableName;
        private final List<OdColumnDef> odColumnList;

        private InternalOdTableDef(String tableName, List<OdColumnDef> odColumnList) {
            this.tableName = tableName;
            this.odColumnList = odColumnList;
        }

        @Override
        public String getTableName() {
            return tableName;
        }

        @Override
        public List<OdColumnDef> getOdColumnDefList() {
            return odColumnList;
        }

    }


    private static class InternalOdColumnDef implements OdColumnDef {

        private final short type;
        private final ExtendedCurrency currency;
        private final String customStyleName;
        private final String defaulCellStyleName;

        private InternalOdColumnDef(short type, ExtendedCurrency currency, String customStyleName, String defaulCellStyleName) {
            this.type = type;
            this.currency = currency;
            this.customStyleName = customStyleName;
            this.defaulCellStyleName = defaulCellStyleName;
        }

        @Override
        public short getColumnStyleFamily() {
            return type;
        }

        @Override
        public ExtendedCurrency getCurrency() {
            return currency;
        }

        @Override
        public String getCustomStyleName() {
            return customStyleName;
        }

        @Override
        public String getDefaultCellStyleName() {
            return defaulCellStyleName;
        }

    }

    public static List<OdColumnDef> wrap(OdColumnDef[] array) {
        return new OdColumnDefList(array);
    }


    private static class OdColumnDefList extends AbstractList<OdColumnDef> implements RandomAccess {

        private final OdColumnDef[] array;

        private OdColumnDefList(OdColumnDef[] array) {
            this.array = array;
        }

        @Override
        public int size() {
            return array.length;
        }

        @Override
        public OdColumnDef get(int index) {
            return array[index];
        }

    }

}
