package com.capgemini.reports.changeobjects.change;

import com.capgemini.framework.teamcenter.authent.TcSession;
import com.capgemini.framework.teamcenter.object.pom.status.StatusEnum.AbstractStatusFilter;
import com.capgemini.framework.teamcenter.object.pom.status.TcReleaseStatus;
import com.capgemini.framework.teamcenter.resolution.filtering.TcTypeExclusionFilter;
import com.capgemini.reports.exceptions.NotSupportedException;
import com.capgemini.reports.snecmaobjects.generic.AbstractGeneric;
import com.teamcenter.soa.client.model.ModelObject;
import com.teamcenter.soa.client.model.strong.ItemRevision;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;

import static com.capgemini.framework.teamcenter.object.SnecmaObjectProperties.*;
import static com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes.*;

/**
 * Class representing a modification.
 */
@Slf4j
public class TcChangeRequestRevision extends AbstractChangeObject {
    private static final long serialVersionUID = -2682203641880659660L;

    public TcChangeRequestRevision(final TcSession session, final ItemRevision itemRevision) {
        super(session, itemRevision);
    }

    public List<FPPRevision> getFppList() {
        session.loadProperties(itemRevision, CM_IMPLEMENTS);
        ModelObject[] implementsObjects = itemRevision.getPropertyObject(CM_IMPLEMENTS).getModelObjectArrayValue();
        session.loadProperties(implementsObjects);
        List<FPPRevision> fppRevisions = new ArrayList<>();
        for (ModelObject implementsObject : implementsObjects) {
            fppRevisions.add(new FPPRevision(session, (ItemRevision) implementsObject));
        }
        return fppRevisions;
    }

    /**
     * Returns true if this CR is a CAD, DCAD, or MACE (actually, {@code PV4_CAD_ACRRevision}, {@code PV4_DCADRevision}, {@code PV4_MACERevision}).
     *
     * @return <code>true</code> if this CR is a CAD, DCAD, or MACE
     */
    public boolean isCadOrDCadOrMace() {
        String changeType = getChangeType();
        return PV4_CAD_ACR_REVISION.equals(changeType) || PV4_DCAD_REVISION.equals(changeType) || PV4_MACE_REVISION.equals(changeType);
    }


    public List<TcChangeNoticeRevision> getChangeNoticesList() {
        List<TcChangeNoticeRevision> changeNotices = new ArrayList<>();
        session.loadProperties(itemRevision, CM_IMPLEMENTED_BY);
        ModelObject[] objects = itemRevision.getPropertyObject(CM_IMPLEMENTED_BY).getModelObjectArrayValue();
        session.loadProperties(objects);
        for (ModelObject currentObject : objects) {
            changeNotices.add(new TcChangeNoticeRevision(session, (ItemRevision) currentObject));
        }
        return changeNotices;
    }

    public List<TcChangeNoticeRevision> getChangeNoticesList(final TcTypeExclusionFilter typeExlusionFilter, final AbstractStatusFilter statusExclusionFilter) {
        List<TcChangeNoticeRevision> changeNotices = new ArrayList<>();
        for (TcChangeNoticeRevision changeNotice : getChangeNoticesList()) {
            if (typeExlusionFilter.isIncluded(changeNotice.getChangeType()) && !hasExcludeStatuses(statusExclusionFilter, changeNotice)) {
                changeNotices.add(changeNotice);
            }
        }
        return changeNotices;
    }

    private boolean hasExcludeStatuses(AbstractStatusFilter statusExclusionFilter, TcChangeNoticeRevision changeNotice) {
        for (TcReleaseStatus status : changeNotice.getReleaseStatusContainingMaturity()) {
            if (statusExclusionFilter.isExcluded(status)) {
                return true;
            }
        }
        return false;
    }

    public String getTypeModSupportProcess() {
        return itemRevision.getPropertyObject(PV4_TYPE_MODIFICATION).getDisplayableValue();
    }

    public List<AbstractGeneric> getListOfGenericRevWithOrWithoutRupture() {
        List<AbstractGeneric> generics = new ArrayList<>();
        List<ModelObject> genericsObjects = new ArrayList<>();
        session.loadProperties(itemRevision, PV_IMP_GENERICS_WITH_INTER, PV_IMP_GENERICS_WITHOUT_INTER);
        genericsObjects.addAll(itemRevision.getPropertyObject(PV_IMP_GENERICS_WITH_INTER).getModelObjectListValue());
        genericsObjects.addAll(itemRevision.getPropertyObject(PV_IMP_GENERICS_WITHOUT_INTER).getModelObjectListValue());
        session.loadProperties(genericsObjects.toArray(new ModelObject[genericsObjects.size()]));
        for (ModelObject genericsObject : genericsObjects) {
            try {
                generics.add(loadGeneric(genericsObject));
            } catch (NotSupportedException e) {
                log.warn("Unsupported object {} found in pseudo-folder {} or {}", genericsObject.getUid(), PV_IMP_GENERICS_WITH_INTER, PV_IMP_GENERICS_WITHOUT_INTER);
            }
        }
        return generics;
    }

    public String getApprobationSO() {
        session.loadProperties(itemRevision, PV_EXTERNAL_APPROBATION);
        ModelObject[] approbationSOarray = itemRevision.getPropertyObject(PV_EXTERNAL_APPROBATION).getModelObjectArrayValue();
        session.loadProperties(approbationSOarray);
        for (ModelObject model : approbationSOarray) {
            if (APPROBATION_SO.equals(model.getTypeObject().getName())) {
                return model.getPropertyObject(PV_NUMERO_APPROBATION).getStringValue();
            }
        }
        return null;
    }
}
