package com.capgemini.reports.definition.r01report.visitors;

import com.capgemini.framework.teamcenter.authent.TcSession;
import com.capgemini.framework.teamcenter.exceptions.KurtException;
import com.capgemini.reports.bomlineholder.BOMLineHolder;
import com.capgemini.reports.definition.r01report.ExecutionR01;
import com.capgemini.reports.definition.r01report.visitors.bomlineholder.R01BOMLineHolderVisitor;
import com.capgemini.reports.execution.mapconstructor.AbstractStaticTemplateMapConstructor;
import com.capgemini.reports.printing.PrintParameters;
import com.capgemini.reports.reports.IReportVisitor;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;

/**
 * Visit a R01 report.
 */
@Slf4j
@EqualsAndHashCode(callSuper = true)
public class R01Visitor extends AbstractStaticTemplateMapConstructor<ExecutionR01, BOMLineHolder> implements IReportVisitor<R01VisitorKeys, String> {

    private static final long serialVersionUID = -943826236018829172L;
    private static final String NULL = "<null>";
    private static final String EMPTY = "";

    protected final R01BOMLineHolderVisitor r01BOMLineHolderVisitor = new R01BOMLineHolderVisitor();

    /**
     * Constructor.
     */
    public R01Visitor() {
        super();
    }

    private static String check(final Object anInput) {
        return anInput == null ? NULL : anInput.toString();
    }

    /**
     * Translate the specific result of the visitor into something the printer can understand.
     */
    private List<Map<String, ?>> translate(final List<Map<R01VisitorKeys, String>> visitorMaps) {
        // Add empty fields in the first line
        Map<R01VisitorKeys, String> firstLine = visitorMaps.get(0);
        // Empty receptor
        firstLine.put(R01VisitorKeys.IDENTIFIANT_RECEPTEUR, EMPTY);
        firstLine.put(R01VisitorKeys.REVISION_RECEPTEUR, EMPTY);
        firstLine.put(R01VisitorKeys.NOM_RECEPTEUR, EMPTY);
        // Empty RF
        firstLine.put(R01VisitorKeys.REPERE_FONCTIONNEL, EMPTY);
        firstLine.put(R01VisitorKeys.REVISION_REPERE_FONCTIONNEL, EMPTY);
        firstLine.put(R01VisitorKeys.IDENTIFIANT_REPERE_FONCTIONNEL, EMPTY);
        firstLine.put(R01VisitorKeys.MAQUETTE, EMPTY);
        firstLine.put(R01VisitorKeys.TRANSFERT_LIEN_LOGISTIQUE, EMPTY);
        firstLine.put(R01VisitorKeys.TRANSFERT_LIEN_MONTAGE, EMPTY);
        firstLine.put(R01VisitorKeys.UIN, EMPTY);
        firstLine.put(R01VisitorKeys.EQUIVALENT_SNSSIN, EMPTY);
        firstLine.put(R01VisitorKeys.RESPONSABLE_REPERE, EMPTY);
        firstLine.put(R01VisitorKeys.SUIVI_MONTAGE, EMPTY);
        // Empty BOM
        firstLine.put(R01VisitorKeys.ALT, EMPTY);
        firstLine.put(R01VisitorKeys.SB, EMPTY);
        firstLine.put(R01VisitorKeys.QUANTITE_CUMULEE, EMPTY);
        firstLine.put(R01VisitorKeys.PANACHE, EMPTY);
        firstLine.put(R01VisitorKeys.QUANTITE, EMPTY);

        // Construct the map list expected by the printer
        List<Map<String, ?>> printerMaps = new ArrayList<>();
        for (Map<R01VisitorKeys, String> visitorMap : visitorMaps) {
            Map<String, String> printerMap = new HashMap<>();
            for (R01VisitorKeys key : R01VisitorKeys.values()) {
                printerMap.put(key.toString(), check(visitorMap.get(key)));
            }
            printerMaps.add(printerMap);
        }

        return printerMaps;
    }

    @Override
    public List<Map<String, ?>> visitReport(final BOMLineHolder holder) {
        List<Map<R01VisitorKeys, String>> visitorMaps = r01BOMLineHolderVisitor.visitTopReceptorBom(holder);
        return translate(visitorMaps);
    }

    @Override
    public void constructDataMaps(TcSession session, final PrintParameters printParameters, final BOMLineHolder data) throws KurtException {
        long start = System.currentTimeMillis();
        if (data == null) {
            throw new NoSuchElementException("No Product structure found");
        }

        // Parse all the snecma objects...
        List<Map<String, ?>> printerMaps = this.visitReport(data);
        printParameters.addReportData(printerMaps);
        log.info("Filtering time : {} ms", System.currentTimeMillis() - start);
    }
}
