package com.capgemini.reports.definition.r19report.snecmaobject;

import com.capgemini.framework.common.LanguageHelper;
import com.capgemini.framework.common.StringHelper;
import com.capgemini.reports.definition.r19report.R19Keys;
import com.capgemini.reports.snecmaobjects.AbstractSnecmaObject;
import com.capgemini.reports.snecmaobjects.generic.AbstractGenericRevision;
import com.capgemini.reports.snecmaobjects.generic.GenericAssembRevision;
import com.capgemini.reports.snecmaobjects.generic.GenericRevision;
import com.capgemini.reports.snecmaobjects.part.*;
import com.capgemini.reports.snecmaobjects.supermodel.SuperModelRevision;

import java.util.EnumMap;
import java.util.Map;


/**
 * Visitor for component objects for the R19.
 */
public class R19ComponentVisitor extends AbstractR19ComponentVisitor {
    private static final long serialVersionUID = 6744199471997128399L;

    private static final String SUFFIXE_REVISION = " Revision";
    private static final String EMPTY_STRING = StringHelper.EMPTY;
    private static final String MATIERE = "matière";
    private static final String SANS_OBJET = "Sans objet";
    private static final String PART_NO_AERO = "Part No Aero";
    private static final String TRANSLATE_TO_PARTNONAERO_FR = "PartNonAéro";

    /**
     * Extracts left side of a string of the form "French text / English text".<br>
     * Separator slash may have *any* number (0+) of white spaces around them.
     */
    private static String french(final String string) {
        return LanguageHelper.french(string);
    }

    @Override
    public Map<R19Keys, String> visitComponent(final DETRevision aDetRev) {
        Map<R19Keys, String> theMap = getAbstractSnecmaObjectProperties(aDetRev);
        theMap.putAll(getAbstractPartProperties(aDetRev));
        theMap.put(R19Keys.TYPE_REFERENCE, french(aDetRev.getTypeDet1()) + " / " + french(aDetRev.getTypeDet2()));
        theMap.put(R19Keys.OBTURATION, french(aDetRev.getObturation()));
        theMap.put(R19Keys.SUIVI_DUREE_VIE, aDetRev.getSuiviDureeVie());
        theMap.put(R19Keys.DUREE_VIE, String.valueOf(aDetRev.getDureeVie()));
        theMap.put(R19Keys.UNITE_DUREE_VIE, aDetRev.getUniteDureeVie());
        theMap.put(R19Keys.DMD, aDetRev.getDMD());
        theMap.put(R19Keys.DMF, aDetRev.getDMF());
        return theMap;
    }

    @Override
    public Map<R19Keys, String> visitComponent(final PartAeroRevision aPartAeroRev) {
        Map<R19Keys, String> theMap = getAbstractSnecmaObjectProperties(aPartAeroRev);
        theMap.putAll(getAbstractPartProperties(aPartAeroRev));
        theMap.put(R19Keys.TYPE_REFERENCE, french(aPartAeroRev.getTypeAero1()) + " / " + french(aPartAeroRev.getTypeAero2()) + " / "
                + french(aPartAeroRev.getTypeAero3()));
        theMap.put(R19Keys.OBTURATION, french(aPartAeroRev.getObturation()));
        theMap.put(R19Keys.SUIVI_DUREE_VIE, aPartAeroRev.getSuiviDureeVie());
        theMap.put(R19Keys.DUREE_VIE, String.valueOf(aPartAeroRev.getDureeVie()));
        theMap.put(R19Keys.UNITE_DUREE_VIE, aPartAeroRev.getUniteDureeVie());
        theMap.put(R19Keys.DMD, aPartAeroRev.getDMD());
        theMap.put(R19Keys.DMF, aPartAeroRev.getDMF());
        return theMap;
    }

    @Override
    public Map<R19Keys, String> visitComponent(final PartNoAeroRevision aPartNoAeroRev) {
        Map<R19Keys, String> theMap = getAbstractSnecmaObjectProperties(aPartNoAeroRev);
        theMap.putAll(getAbstractPartProperties(aPartNoAeroRev));
        theMap.put(R19Keys.TYPE_REFERENCE, french(aPartNoAeroRev.getTypeNoAero()));
        theMap.put(R19Keys.OBTURATION, SANS_OBJET);
        theMap.put(R19Keys.SUIVI_DUREE_VIE, aPartNoAeroRev.getSuiviDureeVie());
        theMap.put(R19Keys.DUREE_VIE, String.valueOf(aPartNoAeroRev.getDureeVie()));
        theMap.put(R19Keys.UNITE_DUREE_VIE, aPartNoAeroRev.getUniteDureeVie());
        theMap.put(R19Keys.DMD, aPartNoAeroRev.getDMD());
        theMap.put(R19Keys.DMF, aPartNoAeroRev.getDMF());
        return theMap;
    }

    @Override
    public Map<R19Keys, String> visitComponent(final PartMatRevision aPartMatRev) {
        Map<R19Keys, String> theMap = getAbstractSnecmaObjectProperties(aPartMatRev);
        theMap.putAll(getAbstractPartProperties(aPartMatRev));
        theMap.put(R19Keys.TYPE_REFERENCE, MATIERE);
        theMap.put(R19Keys.CLASSEMENT, aPartMatRev.getClassementMat());
        theMap.put(R19Keys.SUIVI_UTILISATION, SANS_OBJET);
        theMap.put(R19Keys.DOCUMENT_DE_CONTROLE, SANS_OBJET);
        theMap.put(R19Keys.OBTURATION, SANS_OBJET);
        theMap.put(R19Keys.SUIVI_DUREE_VIE, SANS_OBJET);
        theMap.put(R19Keys.DUREE_VIE, SANS_OBJET);
        theMap.put(R19Keys.UNITE_DUREE_VIE, SANS_OBJET);
        theMap.put(R19Keys.DMD, aPartMatRev.getDMD());
        theMap.put(R19Keys.DMF, aPartMatRev.getDMF());
        return theMap;
    }

    @Override
    public Map<R19Keys, String> visitComponent(final StandardRevision aStandardRev) {
        Map<R19Keys, String> theMap = getAbstractSnecmaObjectProperties(aStandardRev);
        theMap.putAll(getAbstractPartProperties(aStandardRev));
        theMap.put(R19Keys.TYPE_REFERENCE, french(aStandardRev.getTypeStandard()));
        theMap.put(R19Keys.OBTURATION, SANS_OBJET);
        theMap.put(R19Keys.SUIVI_DUREE_VIE, aStandardRev.getSuiviDureeVie());
        theMap.put(R19Keys.DUREE_VIE,String.valueOf(aStandardRev.getDureeVie()));
        theMap.put(R19Keys.UNITE_DUREE_VIE, aStandardRev.getUniteDureeVie());
        theMap.put(R19Keys.DMD, aStandardRev.getDMD());
        theMap.put(R19Keys.DMF, aStandardRev.getDMF());
        return theMap;
    }

    @Override
    public Map<R19Keys, String> visitComponent(SuperModelRevision aSuperModelRev) {
        return null;
    }

    @Override
    public Map<R19Keys, String> visitComponent(final AlternateRevision aAlternateRev) {
        Map<R19Keys, String> theMap = getAbstractSnecmaObjectProperties(aAlternateRev);
        theMap.putAll(getAbstractPartProperties(aAlternateRev));
        theMap.put(R19Keys.TYPE_REFERENCE, french(aAlternateRev.getTypeAlt1()) + " / " + french(aAlternateRev.getTypeAlt2()));
        theMap.put(R19Keys.OBTURATION, french(aAlternateRev.getObturation()));
        theMap.put(R19Keys.SUIVI_DUREE_VIE, aAlternateRev.getSuiviDureeVie());
        theMap.put(R19Keys.DUREE_VIE, String.valueOf(aAlternateRev.getDureeVie()));
        theMap.put(R19Keys.UNITE_DUREE_VIE, aAlternateRev.getUniteDureeVie());
        theMap.put(R19Keys.DMD, aAlternateRev.getDMD());
        theMap.put(R19Keys.DMF, aAlternateRev.getDMF());
        return theMap;
    }

    @Override
    public Map<R19Keys, String> visitComponent(final GenericRevision aGenericRev) {
        Map<R19Keys, String> theMap = getAbstractGenericRevisionProperties(aGenericRev);
        return theMap;
    }

    @Override
    public Map<R19Keys, String> visitComponent(final GenericAssembRevision aGenericAssembRev) {
        Map<R19Keys, String> theMap = getAbstractGenericRevisionProperties(aGenericAssembRev);
        return theMap;
    }

    private Map<R19Keys, String> getAbstractPartProperties(final AbstractPart anAbstractPart) {
        Map<R19Keys, String> theMap = new EnumMap<>(R19Keys.class);
        theMap.put(R19Keys.DESIGNATION_ENG, anAbstractPart.getDesignationEN());
        theMap.put(R19Keys.RESPONSABLE_CONCEPTION, anAbstractPart.getResponsableConception());
        theMap.put(R19Keys.PRODUIT, anAbstractPart.getTypeProduit());
        theMap.put(R19Keys.CLASSEMENT, anAbstractPart.getClassement());
        theMap.put(R19Keys.SUIVI_UTILISATION, french(anAbstractPart.getSuiviUtilisation()));
        theMap.put(R19Keys.DOCUMENT_DE_CONTROLE, french(anAbstractPart.getDocumentControle()));
        return theMap;
    }

    private Map<R19Keys, String> getAbstractSnecmaObjectProperties(final AbstractSnecmaObject anAbstractSnecmaObject) {
        Map<R19Keys, String> theMap = new EnumMap<>(R19Keys.class);

        String valueForKeyObject = removeSuffixeRevision(anAbstractSnecmaObject.getType());
        if (valueForKeyObject.equals(PART_NO_AERO)) {
            valueForKeyObject = translateToPartNonAero(valueForKeyObject);
        }

        theMap.put(R19Keys.OBJET, valueForKeyObject);
        theMap.put(R19Keys.REFERENCE, anAbstractSnecmaObject.getItemId());
        theMap.put(R19Keys.REVISION_REFERENCE, anAbstractSnecmaObject.getRevisionId());
        theMap.put(R19Keys.NOM_REFERENCE, anAbstractSnecmaObject.getName());
        return theMap;
    }

    private Map<R19Keys, String> getAbstractGenericRevisionProperties(final AbstractGenericRevision anAbstractGenericRevision) {
        Map<R19Keys, String> theMap = new EnumMap<>(R19Keys.class);

        String valueForKeyObject = removeSuffixeRevision(anAbstractGenericRevision.getType());

        theMap.put(R19Keys.OBJET, valueForKeyObject);
        theMap.put(R19Keys.REFERENCE, anAbstractGenericRevision.getItemId());
        theMap.put(R19Keys.REVISION_REFERENCE, SANS_OBJET);
        theMap.put(R19Keys.NOM_REFERENCE, anAbstractGenericRevision.getName());
        theMap.put(R19Keys.TYPE_REFERENCE, SANS_OBJET);
        theMap.put(R19Keys.DESIGNATION_ENG, anAbstractGenericRevision.getDesignationEN());
        theMap.put(R19Keys.RESPONSABLE_CONCEPTION, anAbstractGenericRevision.getResponsableConception());
        theMap.put(R19Keys.PRODUIT, SANS_OBJET);
        theMap.put(R19Keys.CLASSEMENT, SANS_OBJET);
        theMap.put(R19Keys.SUIVI_UTILISATION, SANS_OBJET);
        theMap.put(R19Keys.DOCUMENT_DE_CONTROLE, SANS_OBJET);
        theMap.put(R19Keys.OBTURATION, SANS_OBJET);
        theMap.put(R19Keys.SUIVI_DUREE_VIE, SANS_OBJET);
        theMap.put(R19Keys.DUREE_VIE, SANS_OBJET);
        theMap.put(R19Keys.UNITE_DUREE_VIE, SANS_OBJET);
        theMap.put(R19Keys.DMD, SANS_OBJET);
        theMap.put(R19Keys.DMF, SANS_OBJET);
        return theMap;
    }

    /* Remove suffix Revision from an Part ex: Part Revision become Part */
    private String removeSuffixeRevision(final String part) {
        return part.replace(SUFFIXE_REVISION, EMPTY_STRING).trim();
    }

    private String translateToPartNonAero(final String partNoAero) {
        return partNoAero.replace(partNoAero, TRANSLATE_TO_PARTNONAERO_FR);
    }

}
