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

import com.capgemini.framework.common.StringHelper;
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.generic.AbstractGenericRevision;
import com.capgemini.reports.snecmaobjects.product.ProductRevision;
import com.capgemini.reports.snecmaobjects.rf.RFGenericRevision;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

/**
 * Represents a Product/Generic/RfGeneric.
 *
 * @param <U> a Transformer object producing results of type T
 * @param <T> the result of a transformation by object of type U
 */
@Getter
@Slf4j
public abstract class AbstractProductGeneric<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 productReceptorBL;
    private final BOMLineHolder genericComponentBL;
    private final BOMLineHolder rfGenericComponentBL;
    private final int lineNumber;
    private final ProductRevision productReceptor;
    private final AbstractGenericRevision genericComponent;
    private final RFGenericRevision rfGenericComponent;
    protected final TcSession session;

    /**
     * Constructor for a link Product-->Generic-->RF Generic.
     *
     * @param session
     * @param productReceptorBL    the product
     * @param genericComponentBL   the generic
     * @param rfGenericComponentBL the RF Generic of the Generic
     * @param lineNumber           a line number, identifying uniquely and orderly this triplet in the configuration.
     */
    public AbstractProductGeneric(TcSession session, final BOMLineHolder productReceptorBL, final BOMLineHolder genericComponentBL,
                                  final BOMLineHolder rfGenericComponentBL, final int lineNumber) {
        this.session = session;
        this.productReceptorBL = productReceptorBL;
        this.genericComponentBL = genericComponentBL;
        this.rfGenericComponentBL = rfGenericComponentBL;
        this.lineNumber = lineNumber;
        this.productReceptor = (ProductRevision) productReceptorBL.getSnecmaObject();
        this.genericComponent = (AbstractGenericRevision) genericComponentBL.getSnecmaObject();
        this.rfGenericComponent = (RFGenericRevision) rfGenericComponentBL.getSnecmaObject();
    }

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

    /**
     * Compares this {@link AbstractProductGeneric} to an other one.
     *
     * @param other the other {@link AbstractProductGeneric}
     * @return a difference number. 0 if equal.
     */
    public int compareTo(final AbstractProductGeneric<T, U> other) {
        int cmp = productReceptorBL.getSnecmaObject().getItemId().compareTo(other.productReceptorBL.getSnecmaObject().getItemId());
        if (cmp != 0) {
            return cmp;
        } else {
            cmp = rfGenericComponent.getName().compareTo(other.rfGenericComponent.getName());
            if (cmp != 0) {
                return cmp;
            } else {
                return genericComponent.getItemId().compareTo(other.genericComponent.getItemId());
            }
        }
    }

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

    @Override
    public String getLineId() {
        return productReceptorBL.getSnecmaObject().getItemId() + "/" + rfGenericComponent.getName() + "/" + genericComponent.getItemId();
    }

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

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

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

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

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

    @Override
    public String getResponsableRepere() {
        try {
            if (rfGenericComponent.isRFGeneric()) {
                return BOMLineHolderHelper.findRfAdmin(rfGenericComponentBL).getResponsableRepere();
            } else if (rfGenericComponent.isRFPartOrPartAssemb()) {
                if (SnecmaObjectTypes.RF_PART_ASSEMB_REVISION.equals(rfGenericComponent.getType())) {
                    return BOMLineHolderHelper.findRfAdminA(rfGenericComponentBL).getResponsableRepere();
                } else {
                    return BOMLineHolderHelper.findRfAdmin(rfGenericComponentBL).getResponsableRepere();
                }
            }
        } catch (KurtException e) {
            log.warn("Unable to find a RF Admin below Rf " + rfGenericComponent.getName(), e);
            return EMPTY;
        }
        return EMPTY;
    }

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

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

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

    @Override
    public String getTypeReference() {
        String type = genericComponent.getType();
        if (SnecmaObjectTypes.GENERIC_REVISION.equals(type)) {
            return "Générique";
        } else if (SnecmaObjectTypes.GENERIC_ASSEMB_REVISION.equals(type)) {
            return "Générique Montage";
        }
        return "";
    }

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

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

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

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

    @Override
    public String getResponsableConception() {
        if (genericComponent.isGeneric()) {
            return genericComponent.getResponsableConception();
        }
        return EMPTY;
    }

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

    @Override
    public String getClassement() {
        return "-";
    }

    @Override
    public String getSuiviUtilisation() {
        return OUI;
    }

    @Override
    public String getSuiviDureeVie() {
        return NON;
    }

    @Override
    public String[] getSuppliersList() {
        return new String[0];
    }

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

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

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

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

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

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

    @Override
    public Double getMass() {
        return null;
    }

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

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

}
