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

import com.capgemini.framework.common.ResourceHelper;
import com.capgemini.framework.common.TeamcenterDateFormatter;
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.r22report.ExecutionR22;
import com.capgemini.reports.definition.r22report.ExecutionR22.ReportDataR22;
import com.capgemini.reports.definition.r22report.visitors.bomlineholder.R22BOMLineHolderVisitor;
import com.capgemini.reports.exceptions.FileLoadingException;
import com.capgemini.reports.execution.mapconstructor.AbstractStaticTemplateMapConstructor;
import com.capgemini.reports.printing.PrintParameters;
import com.capgemini.reports.reports.IReportVisitor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.awt.image.BufferedImage;
import java.util.*;

/**
 * Visit a R22 report.
 */
public class R22Visitor extends AbstractStaticTemplateMapConstructor<ExecutionR22, ReportDataR22> implements IReportVisitor<R22VisitorKeys, String> {
    private static final long serialVersionUID = -1530604820422919903L;
    private static final Logger LOGGER = LoggerFactory.getLogger(R22Visitor.class);

    private static final String SNECMA_LOGO = "/Jasper/images/Snecma_logo.png";
    private static final String EMPTY = "";
    private static final String MULTI_NIVEAUX = "Multi-niveaux";

    private final R22BOMLineHolderVisitor r22BOMLineHolderVisitor = new R22BOMLineHolderVisitor();

    public R22Visitor() {
        super();
    }

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

    private List<Map<String, ?>> translate(final List<Map<R22VisitorKeys, String>> visitorMaps) {
        // Add empty fields in the first line
        Map<R22VisitorKeys, String> firstLine = visitorMaps.get(0);

        // Empty receptor
        firstLine.put(R22VisitorKeys.RECEPTEUR, EMPTY);
        firstLine.put(R22VisitorKeys.REPERE_FONCTIONNEL_REVISION, EMPTY);
        firstLine.put(R22VisitorKeys.RESPONSABLE_REPERE, EMPTY);
        firstLine.put(R22VisitorKeys.ALT, EMPTY);
        firstLine.put(R22VisitorKeys.SB, EMPTY);
        firstLine.put(R22VisitorKeys.NQC, EMPTY);
        firstLine.put(R22VisitorKeys.PANACHAGE, EMPTY);
        firstLine.put(R22VisitorKeys.COEFF, EMPTY);

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

    /**
     * Add additional elements for header of R22 report.
     *
     * @param aDateNow        Current date as string
     * @param ressource       url resource
     * @param clausePropriete the 'clause de propriete' Snecma
     * @return map of additional elements
     */
    private EnumMap<R22VisitorParametersKeys, Object> addAdditionalParameters(final String aDateNow, final String ressource,
                                                                              final String clausePropriete) {
        EnumMap<R22VisitorParametersKeys, Object> map = new EnumMap<>(R22VisitorParametersKeys.class);
        map.put(R22VisitorParametersKeys.CLAUSE_DE_PROPRIETE, clausePropriete);
        map.put(R22VisitorParametersKeys.DATE_EFFECTIVITE, aDateNow);
        map.put(R22VisitorParametersKeys.DATE_TRAITEMENT, aDateNow);
        map.put(R22VisitorParametersKeys.NIVEAU, MULTI_NIVEAUX);
        map.put(R22VisitorParametersKeys.REFERENCE_ARTICLE, r22BOMLineHolderVisitor.getReferenceItem());

        try {
            BufferedImage image = ResourceHelper.loadImage(ressource);
            map.put(R22VisitorParametersKeys.LOGO_SNECMA, image);
        } catch (FileLoadingException e) {
            LOGGER.warn("Could not load Snecma logo", e);
        }

        LOGGER.debug("MAP {}", map);

        return map;
    }

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

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

        // Parse all the snecma objects...
        List<Map<String, ?>> printerMaps = this.visitReport(data.getTopLine());
        LOGGER.debug("Printer map size {}", printerMaps.size());
        printParameters.addReportData(printerMaps);

        String dateNowInFrench = TeamcenterDateFormatter.formatCalendarToFrench(Calendar.getInstance());
        EnumMap<R22VisitorParametersKeys, Object> additionalParameters = addAdditionalParameters(dateNowInFrench, SNECMA_LOGO, data.getClausePropriete());
        printParameters.addReportParameters(additionalParameters);

        LOGGER.info(EXECUTION_TIME_XXX_MS_FOR_YYY, System.currentTimeMillis() - start, "data filtering");
    }
}
