package com.capgemini.reports.definition.r23report.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.r23report.ExecutionR23;
import com.capgemini.reports.definition.r23report.visitors.bomlineholder.R23BOMLineHolderVisitor;
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 R23 report.
 */
@Slf4j
@EqualsAndHashCode(callSuper = true)
public class R23Visitor extends AbstractStaticTemplateMapConstructor<ExecutionR23, BOMLineHolder> implements IReportVisitor<R23VisitorKeys, String> {
  private static final long serialVersionUID = 3013480234676995245L;

  private static final String NULL = "<null>";
  private static final String EMPTY = "";

  protected final R23BOMLineHolderVisitor r23BOMLineHolderVisitor = new R23BOMLineHolderVisitor();
  private final int unitNumber;

  /**
   * Constructor.
   */
  public R23Visitor(final int unitNumber) {
    this.unitNumber = unitNumber;
  }

  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<R23VisitorKeys, String>> visitorMaps) {
    // Add empty fields in the first line
    Map<R23VisitorKeys, String> firstLine = visitorMaps.get(0);
    // Empty receptor
    firstLine.put(R23VisitorKeys.UNIT_NUM, String.valueOf(unitNumber));
    firstLine.put(R23VisitorKeys.IDENTIFIANT_RECEPTEUR, EMPTY);
    firstLine.put(R23VisitorKeys.REVISION_RECEPTEUR, EMPTY);
    firstLine.put(R23VisitorKeys.NOM_RECEPTEUR, EMPTY);
    // Empty RF
    firstLine.put(R23VisitorKeys.REPERE_FONCTIONNEL, EMPTY);
    firstLine.put(R23VisitorKeys.REVISION_REPERE_FONCTIONNEL, EMPTY);
    firstLine.put(R23VisitorKeys.IDENTIFIANT_REPERE_FONCTIONNEL, EMPTY);
    firstLine.put(R23VisitorKeys.MAQUETTE, EMPTY);
    firstLine.put(R23VisitorKeys.TRANSFERT_LIEN_LOGISTIQUE, EMPTY);
    firstLine.put(R23VisitorKeys.TRANSFERT_LIEN_MONTAGE, EMPTY);
    firstLine.put(R23VisitorKeys.UIN, EMPTY);
    firstLine.put(R23VisitorKeys.EQUIVALENT_SNSSIN, EMPTY);
    firstLine.put(R23VisitorKeys.RESPONSABLE_REPERE, EMPTY);
    firstLine.put(R23VisitorKeys.SUIVI_MONTAGE, EMPTY);
    firstLine.put(R23VisitorKeys.IDENTIFIANT_RF_ADMIN, EMPTY);
    firstLine.put(R23VisitorKeys.REVISION_RF_ADMIN, EMPTY);
    firstLine.put(R23VisitorKeys.IDENTIFIANT_RF_ADMIN_AP, EMPTY);
    firstLine.put(R23VisitorKeys.REVISION_RF_ADMIN_AP, EMPTY);
    firstLine.put(R23VisitorKeys.FRONTIERE_AVION, EMPTY);
    firstLine.put(R23VisitorKeys.FRONTIERE_COOPERANT, EMPTY);
    firstLine.put(R23VisitorKeys.GEOMETRIE_PIECE_RIGIDE, EMPTY);
    firstLine.put(R23VisitorKeys.GEOMETRIE_SIMPLIFIE_RIGIDE, EMPTY);
    firstLine.put(R23VisitorKeys.ENVELOPPE_DE_CINEMATIQUE, EMPTY);
    firstLine.put(R23VisitorKeys.ENVELOPPE_DE_MAINTENANCE, EMPTY);
    firstLine.put(R23VisitorKeys.ENVELOPPE_DE_MONTAGE_DEMONTAGE, EMPTY);
    firstLine.put(R23VisitorKeys.TRACE_AXIALE, EMPTY);
    firstLine.put(R23VisitorKeys.INTERFACE, EMPTY);
    firstLine.put(R23VisitorKeys.PROJECT_MOTEUR, EMPTY);
    firstLine.put(R23VisitorKeys.MAQUETTE_ECHANGEABLE, EMPTY);
    firstLine.put(R23VisitorKeys.WORKPACKAGE, EMPTY);
    // Empty BOM
    firstLine.put(R23VisitorKeys.ALT, EMPTY);
    firstLine.put(R23VisitorKeys.SB, EMPTY);
    firstLine.put(R23VisitorKeys.QUANTITE_CUMULEE, EMPTY);
    firstLine.put(R23VisitorKeys.PANACHE, EMPTY);
    firstLine.put(R23VisitorKeys.QUANTITE, EMPTY);

    // Construct the map list expected by the printer
    List<Map<String, ?>> printerMaps = new ArrayList<>();
    for (Map<R23VisitorKeys, String> visitorMap : visitorMaps) {
      Map<String, String> printerMap = new HashMap<>();
      for (R23VisitorKeys key : R23VisitorKeys.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<R23VisitorKeys, String>> visitorMaps = r23BOMLineHolderVisitor.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);
  }
}
