package com.capgemini.reports.bomlineholder.flattener.line;

import com.capgemini.framework.teamcenter.authent.TcSession;
import com.capgemini.framework.teamcenter.exceptions.KurtException;
import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes;
import com.capgemini.reports.bomlineholder.BOMLineHolder;
import com.capgemini.reports.bomlineholder.BOMLineHolderHelper;
import com.capgemini.reports.snecmaobjects.part.*;
import com.capgemini.reports.snecmaobjects.rf.AbstractRF;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

/**
 * Represents a Part/RF Part/Part.
 *
 * @param <T> the result of a transformation by object of type U
 * @param <U> a Transformer object producing results of type T
 */
@Getter
@Slf4j
public abstract class AbstractPartRfPart<T, U> implements SnecmaLine<T, U> {

    private static final String NON = "Non";
    private static final String OUI = "Oui";
    private static final String EMPTY = "";

    private final BOMLineHolder partReceptorBL;
    private final BOMLineHolder rfPartComponentBL;
    private final BOMLineHolder partComponentBL;
    private final int lineNumber;

    private final AbstractPart partReceptor;
    private final AbstractRF rfPartComponent;
    private final AbstractPart partComponent;
    protected final TcSession session;

    /**
     * Constructor using a Part receptor, a RF Part component , and a Part component (all bomLineHolders).
     *
     * @param session
     * @param partReceptor    the receptor Part
     * @param rfPartComponent the RF Part
     * @param partComponent   the Component Part
     * @param lineNumber      a line number, identifying uniquely and orderly this triplet in the configuration.
     */
    public AbstractPartRfPart(final TcSession session, final BOMLineHolder partReceptor, final BOMLineHolder rfPartComponent, final BOMLineHolder partComponent,
                              final int lineNumber) {
        this.session = session;
        this.partReceptorBL = partReceptor;
        this.rfPartComponentBL = rfPartComponent;
        this.partComponentBL = partComponent;
        this.lineNumber = lineNumber;
        this.partReceptor = (AbstractPart) partReceptorBL.getSnecmaObject();
        this.rfPartComponent = (AbstractRF) rfPartComponentBL.getSnecmaObject();
        this.partComponent = (AbstractPart) partComponentBL.getSnecmaObject();
    }

    @Override
    public int compareTo(final SnecmaLine<T, U> other) {
        if (this.getClass().isAssignableFrom(other.getClass())) {
            return compareTo((AbstractPartRfPart<T, U>) other);
        } else {
            return getLineId().compareTo(other.getLineId());
        }
    }

    /**
     * Compares this {@link AbstractPartRfPart} to an other one.
     *
     * @param other the other {@link AbstractPartRfPart}
     * @return a difference number. 0 if equal.
     */
    public int compareTo(final AbstractPartRfPart<T, U> other) {
        int cmp = partReceptor.getItemId().compareTo(other.partReceptor.getItemId());
        if (cmp == 0) {
            cmp = rfPartComponent.getName().compareTo(other.rfPartComponent.getName());
            if (cmp == 0) {
                if (partComponentBL == null) {
                    return other.partComponentBL == null ? 0 : 1;
                }
                return partComponent.getItemId().compareTo(other.partComponent.getItemId());
            }
        }
        return cmp;
    }

    @Override
    public String toString() {
        return "PartRfPart(" + getLineId() + ")";
    }

    @Override
    public String getLineId() {
        return partReceptor.getItemId() + "/" + rfPartComponent.getName() + "/" + partComponent.getItemId();
    }

    @Override
    public String getIDReceptor() {
        return partReceptor.getItemId();
    }

    @Override
    public String getNameReceptor() {
        return partReceptor.getName();
    }

    @Override
    public String getRevisionReceptor() {
        return partReceptor.getRevisionId();
    }

    @Override
    public String getRepereName() {
        return rfPartComponent.getName();
    }

    @Override
    public String getRepereRevision() {
        return rfPartComponent.getRevisionId();
    }

    @Override
    public String getResponsableRepere() {
        try {
            String resp;
            if (SnecmaObjectTypes.RF_PART_ASSEMB_REVISION.equals(rfPartComponent.getType())) {
                resp = BOMLineHolderHelper.findRfAdminA(this.getRfPartComponentBL()).getResponsableRepere();
            } else {
                resp = BOMLineHolderHelper.findRfAdmin(this.getRfPartComponentBL()).getResponsableRepere();
            }
            return resp;
        } catch (KurtException e) {
            log.warn("Unable to find the correct RF Admins below Rf: " + rfPartComponent.getName(), e);
            return EMPTY;
        }
    }

    @Override
    public String getSuiviMontage() {
        try {
            String suiviMontage;
            if (rfPartComponent.isRFGeneric()) {
                suiviMontage = NON;
            } else if (rfPartComponent.isRFPartOrPartAssemb()) {
                if (SnecmaObjectTypes.RF_PART_ASSEMB_REVISION.equals(rfPartComponent.getType())) {
                    suiviMontage = BOMLineHolderHelper.findRfAdminA(rfPartComponentBL).getSuiviMontage();
                } else {
                    suiviMontage = BOMLineHolderHelper.findRfAdminAP(rfPartComponentBL).getSuiviMontage();
                }
            } else {
                suiviMontage = EMPTY;
            }
            return suiviMontage;
        } catch (KurtException e) {
            log.warn("Unable to find the correct RF Admins A/AP below Rf Part / RF Part Assemb: " + rfPartComponent.getName(), e);
            return EMPTY;
        }
    }

    @Override
    public String getIDComponent() {
        return partComponent.getItemId();
    }

    @Override
    public String getIDRevisionComponent() {
        return partComponent.getRevisionId();
    }

    @Override
    public String getTypeReference() {
        return PartTypeExtractorHelper.extractType(partComponent);
    }

    @Override
    public String getNameReference() {
        return partComponent.getName();
    }

    @Override
    public String getReferenceConceptor() {
        return partComponent.getRefCompleteConcepteur();
    }

    @Override
    public String getReferenceTransposed() {
        return partComponent.getRefTransposeeSnecma();
    }

    @Override
    public String getReferenceAssociated() {
        return partComponent.getRefAssociee();
    }

    @Override
    public String getResponsableConception() {
        return partComponent.getResponsableConception();
    }

    @Override
    public String getArticleGestion() {
        if (SnecmaObjectTypes.isA(partComponent.getType(), SnecmaObjectTypes.DET_REVISION, SnecmaObjectTypes.ALTERNATE_REVISION,
                SnecmaObjectTypes.PART_ASSEMB_REVISION)) {
            return OUI;
        }
        return EMPTY;
    }

    @Override
    public String getClassement() {
        if (SnecmaObjectTypes.PART_MAT_REVISION.equals(partComponent.getType())) {
            return ((PartMatRevision) partComponent).getClassementMat();
        } else {
            return partComponent.getClassement();
        }
    }

    @Override
    public String getSuiviUtilisation() {
        return partComponent.getSuiviUtilisation();
    }

    @Override
    public String getSuiviDureeVie() {
        return partComponent.getSuiviDureeVie();
    }

    @Override
    public String[] getSuppliersList() {
        String type = partComponent.getType();
        String[] lst;
        if (SnecmaObjectTypes.PART_AERO_REVISION.equals(type)) {
            lst = ((PartAeroRevision) partComponent).getLstFournisseurs();
        } else if (SnecmaObjectTypes.PART_MAT_REVISION.equals(type)) {
            lst = ((PartMatRevision) partComponent).getLstFournisseurs();
        } else if (SnecmaObjectTypes.STANDARD_REVISION.equals(type)) {
            lst = ((StandardRevision) partComponent).getLstFournisseurs();
        } else if (SnecmaObjectTypes.DET_REVISION.equals(type)) {
            lst = ((DETRevision) partComponent).getLstFournisseurs();
        } else if (SnecmaObjectTypes.ALTERNATE_REVISION.equals(type)) {
            lst = ((AlternateRevision) partComponent).getLstFournisseurs();
        } else {
            lst = new String[0];
        }
        return lst;
    }

    @Override
    public String getALT() {
        return partComponentBL.getBomAlt();
    }

    @Override
    public String getSB() {
        return partComponentBL.getBomSb();
    }

    @Override
    public String getQuantiteCumulee() {
        return partComponentBL.getBomQtyCumul();
    }

    @Override
    public String getPanachage() {
        return partComponentBL.getBomPanache();
    }

    @Override
    public String getQuantite() {
        return partComponentBL.getBomQty();
    }

    @Override
    public String getMaquetteInterneExterne() {
        return EMPTY;
    }

    @Override
    public Double getMass() {
        return partComponent.getMass();
    }

    @Override
    public String getMassUnit() {
        return partComponent.getMassUnit();
    }

    @Override
    public String getDesignationENG() {
        return partComponent.getDesignationEN();
    }

}
