package com.capgemini.reports.definition.r15r16r17reports.r15r17reports;

import com.capgemini.reports.definition.r15r16r17reports.AbstractR15R16R17Printer;
import com.capgemini.reports.definition.r15r16r17reports.CommunR15R16R17ComponentVisitor;
import com.capgemini.reports.definition.r15r16r17reports.R15R16R17R24R25Keys;
import com.capgemini.reports.definition.r15r16r17reports.R15R16R17R24R25Keys.Page2;
import com.capgemini.reports.definition.r15r16r17reports.r15r17reports.r17report.ExecutionR17;
import com.capgemini.reports.documentationobjects.DocDrawing;
import com.capgemini.reports.documentationobjects.DocGeometry;
import com.capgemini.reports.execution.AbstractExecutionReport;
import com.capgemini.reports.printing.PrintParameters;
import com.capgemini.reports.snecmaobjects.visitor.IComponentVisitor;
import lombok.EqualsAndHashCode;

import java.util.ArrayList;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;

/**
 * This class allows printing of several elements that are found in both the R17 and R15 reports.
 *
 * @param <T> describes which report's {@link AbstractExecutionReport} this printer will print. Must be a subclass of {@link AbstractExecutionR15R17}.
 */
@EqualsAndHashCode(callSuper = true)
public abstract class AbstractR15R17Printer<T extends AbstractExecutionR15R17<T>> extends AbstractR15R16R17Printer<T> {

    private static final long serialVersionUID = 6353372020574746542L;

    @Override
    protected List<Map<Page2, String>> addExtraDocLines(final T execution) {
        List<Map<Page2, String>> dataTable = new ArrayList<>();
        boolean isFrench = execution.isFrench();
        for (DocGeometry geometry : execution.getDocGeometryList()) {
            dataTable.add(getDocGeometryLine(geometry, isFrench));
        }
        String itemId = execution.getItemId();
        for (DocDrawing drawing : execution.getDocDrawingList()) {
            dataTable.add(getDocDrawingLine(drawing, isFrench, execution.getTypeProduit(), itemId));
        }
        return dataTable;
    }

    private Map<Page2, String> getDocDrawingLine(final DocDrawing drawing, final boolean isFrench, final String typeProduit, final String itemID) {
        String identifier;
        if (isNotAuthorized(typeProduit)) {
            identifier = itemID;
        } else {
            identifier = drawing.getDocId();
        }
        Map<Page2, String> line = new EnumMap<>(Page2.class);
        line.put(Page2.DOC_NUMBER, identifier);
        line.put(Page2.ISSUE, drawing.getIndicePlan());
        line.put(Page2.DOC_TYPE, isFrench ? "Représentation 2D" : "Drawing");
        line.put(Page2.DOC_TITLE, isFrench ? drawing.getName() : drawing.getDesignationEn());
        return line;
    }

    private Map<Page2, String> getDocGeometryLine(final DocGeometry geometry, final boolean isFrench) {
        Map<Page2, String> line = new EnumMap<>(Page2.class);
        line.put(Page2.DOC_NUMBER, geometry.getDocId());
        line.put(Page2.ISSUE, geometry.getIndiceCartouche());
        line.put(Page2.DOC_TYPE, isFrench ? "Modèle 3D" : "3D Model");
        line.put(Page2.DOC_TITLE, geometry.getDesignationEN());
        return line;
    }

    @Override
    protected void addOptionalParameters(final T execution, final PrintParameters mainReport) {
        // Add common parameters between R15 and R17
      Map<R15R16R17R24R25Keys, Object> params = new EnumMap<>(R15R16R17R24R25Keys.class);
      params.put(R15R16R17R24R25Keys.MT_NUMBER, execution.getVarMt());
      params.put(R15R16R17R24R25Keys.PREVIOUS_RELEASE_DATE, execution.getPreviousReleaseDate());
        params.putAll(execution.getSnecmaObject().accept(getVisitor(execution.isFrench())));
        mainReport.addReportParameters(params);

        // Add specific parameters to each sub-report
        addSpecificParameters(execution, mainReport);
    }

    /**
     * Adds parameters that are specific to each subclass and not common to R15-R17. In particular, R15Printer will want to add a few values.
     *
     * @param execution  the data-bearing {@link ExecutionR17}
     * @param mainReport the {@link PrintParameters}
     */
    protected abstract void addSpecificParameters(final T execution, final PrintParameters mainReport);

    @Override
    protected IComponentVisitor<Map<R15R16R17R24R25Keys, String>> getVisitor(final boolean isFrench) {
        return new CommunR15R16R17ComponentVisitor(isFrench);
    }

}
