package com.capgemini.reports.definition.r10report;

import com.capgemini.framework.common.DoubleFormatter;
import com.capgemini.framework.common.StringHelper;
import com.capgemini.framework.teamcenter.authent.TcSession;
import com.capgemini.framework.teamcenter.exceptions.KurtException;
import com.capgemini.reports.bomlineholder.flattener.line.SnecmaLine;
import com.capgemini.reports.definition.r10report.ExecutionR10.ReportDataR10;
import com.capgemini.reports.documentationobjects.AbstractDoc;
import com.capgemini.reports.execution.mapconstructor.AbstractStaticTemplateMapConstructor;
import com.capgemini.reports.printing.PrintParameters;
import lombok.extern.slf4j.Slf4j;

import java.util.*;

/**
 * Extracts the relevant data obtained from TC into the expected List of Maps for Jasper.
 */
@Slf4j
public class R10Printer extends AbstractStaticTemplateMapConstructor<ExecutionR10, ReportDataR10> {
    private static final long serialVersionUID = 2418903684813779698L;

    private static final int SIGNIFICANT_DIGITS = 6;
    private static final Map<R10Keys, String> EMPTY_BOM_MAP = new EnumMap<>(R10Keys.class);

    static {
        EMPTY_BOM_MAP.put(R10Keys.COMPONENT_CLASSEMENT, "");
        EMPTY_BOM_MAP.put(R10Keys.COMPONENT_DESIGN_MANAGER, "");
        EMPTY_BOM_MAP.put(R10Keys.COMPONENT_ID, "");
        EMPTY_BOM_MAP.put(R10Keys.COMPONENT_MASS, "");
        EMPTY_BOM_MAP.put(R10Keys.COMPONENT_MASS_UNIT, "");
        EMPTY_BOM_MAP.put(R10Keys.COMPONENT_NAME, "");
        EMPTY_BOM_MAP.put(R10Keys.COMPONENT_NAME_ENG, "");
        EMPTY_BOM_MAP.put(R10Keys.COMPONENT_REF_TRANSPOSED, "");
        EMPTY_BOM_MAP.put(R10Keys.COMPONENT_REVISION, "");
        EMPTY_BOM_MAP.put(R10Keys.COMPONENT_TYPE, "");
        EMPTY_BOM_MAP.put(R10Keys.QUANTITY, "");
        EMPTY_BOM_MAP.put(R10Keys.RECEPTOR_ID, "");
        EMPTY_BOM_MAP.put(R10Keys.RECEPTOR_NAME, "");
        EMPTY_BOM_MAP.put(R10Keys.RECEPTOR_REVISION, "");
        EMPTY_BOM_MAP.put(R10Keys.REPERE_NAME, "");
        EMPTY_BOM_MAP.put(R10Keys.REPERE_REVISION, "");
        EMPTY_BOM_MAP.put(R10Keys.RESPONSABLE_REPERE, "");
    }

    private final Calendar effectivityDate;

    public R10Printer(final Calendar effectivityDate) {
        this.effectivityDate = effectivityDate;
    }

    @Override
    public void constructDataMaps(final TcSession session, final PrintParameters printParameters, final ReportDataR10 reportData) throws KurtException {
        log.info("Browsing the Snecma Objects");
        R10BomLineFlattener flattener = new R10BomLineFlattener(session);
        flattener.visitTopReceptorBom(session, reportData.getConfig());

        // Degroup with doc data
        log.info("Regrouping conf elements with their documents");
        List<Map<R10Keys, ?>> result = new ArrayList<>();
        Map<String, AbstractDoc> docCache = new HashMap<>();
        for (SnecmaLine<List<Map<R10Keys, String>>, DocumentExtractor> elem : flattener.getConfig()) {
            Map<R10Keys, String> bomMap = generateCommonBomMap(elem);
            List<Map<R10Keys, String>> docMaps = elem.transform(new DocumentExtractor(effectivityDate, docCache));
            // Put the bom info in the 1st line, leave the rest blank
            Iterator<Map<R10Keys, String>> docIterator = docMaps.iterator();
            docIterator.next().putAll(bomMap);
            // Put empty fields in the rest
            while (docIterator.hasNext()) {
                docIterator.next().putAll(EMPTY_BOM_MAP);
            }
            result.addAll(docMaps);
        }
        log.info("{} Lines generated for {} parts.", result.size(), flattener.getConfig().size());
        printParameters.addReportDataFromEnum(result);
    }

    private Map<R10Keys, String> generateCommonBomMap(final SnecmaLine<List<Map<R10Keys, String>>, DocumentExtractor> line) {
        String massStr;
        if (line.getMass() == null) {
            massStr = StringHelper.EMPTY; // when no mass is set (ex: receptor without component) print nothing
        } else {
            massStr = DoubleFormatter.toSignificantDigits(line.getMass(), SIGNIFICANT_DIGITS);
        }
        Map<R10Keys, String> map = new EnumMap<>(R10Keys.class);
        map.put(R10Keys.RECEPTOR_ID, line.getIDReceptor());
        map.put(R10Keys.RECEPTOR_NAME, line.getNameReceptor());
        map.put(R10Keys.RECEPTOR_REVISION, line.getRevisionReceptor());
        map.put(R10Keys.REPERE_NAME, line.getRepereName());
        map.put(R10Keys.REPERE_REVISION, line.getRepereRevision());
        map.put(R10Keys.RESPONSABLE_REPERE, line.getResponsableRepere());
        map.put(R10Keys.COMPONENT_ID, line.getIDComponent());
        map.put(R10Keys.COMPONENT_REVISION, line.getIDRevisionComponent());
        map.put(R10Keys.COMPONENT_NAME, line.getNameReference());
        map.put(R10Keys.COMPONENT_NAME_ENG, line.getDesignationENG());
        map.put(R10Keys.COMPONENT_TYPE, line.getTypeReference());
        map.put(R10Keys.COMPONENT_REF_TRANSPOSED, line.getReferenceTransposed());
        map.put(R10Keys.COMPONENT_DESIGN_MANAGER, line.getResponsableConception());
        map.put(R10Keys.COMPONENT_CLASSEMENT, line.getClassement());
        map.put(R10Keys.COMPONENT_MASS, massStr);
        map.put(R10Keys.COMPONENT_MASS_UNIT, line.getMassUnit());
        map.put(R10Keys.QUANTITY, line.getQuantite());
        return map;
    }
}
