package com.capgemini.reports.releasestatus;

import com.capgemini.framework.common.TeamcenterDateFormatter;
import com.capgemini.framework.teamcenter.authent.TcSession;
import com.capgemini.framework.teamcenter.object.pom.status.StatusEnum;
import com.capgemini.framework.teamcenter.queries.saved.modelobject.ItemRevisionQuery;
import com.capgemini.reports.teamcenter.ObjectInfoHelper;
import com.google.common.base.Optional;
import com.teamcenter.soa.client.model.strong.Item;
import com.teamcenter.soa.client.model.strong.ItemRevision;
import lombok.extern.slf4j.Slf4j;

import java.util.Calendar;
import java.util.List;

/**
 * This class is a Default Selector of Revision. Its job is to return the latest {@link ItemRevision} of the {@link Item}. <br>
 * First looks for the revision which has the TcReleaseStatus with the latest release_date (that is before the embedded deadline).<br>
 * If no Revision have a TcReleaseStatus, or if none of these statuses have a release date, then returns the Revision with the latest last_mod_date (that is before the provided deadline).
 */
@Slf4j
public class DefaultRevisionSelector implements RevisionSelector {

    private static final long serialVersionUID = 8373335997828920471L;

    private final Calendar deadline;

    private final StatusEnum[] allowedStatuses;

    /**
     * Builds a {@link DefaultRevisionSelector} with a {@link Calendar} as a deadline (for release date/mod date) and an (optional) list of allowed TcReleaseStatus.
     *
     * @param deadline        deadline: no status set after this date is allowed / no Revision modified after this date either. If null, all dates are allowed.
     * @param allowedStatuses a list of allowed {@link StatusEnum}. If empty, all status are accepted
     */
    public DefaultRevisionSelector(final Calendar deadline, final StatusEnum... allowedStatuses) {
        this.deadline = deadline;
        this.allowedStatuses = allowedStatuses;
    }

    /**
     * Returns the latest {@link ItemRevision} of the {@link Item}. <br>
     * First looks for the revision which has the TcReleaseStatus with the latest release_date (that is before the embedded deadline). This TcReleaseStatus must also be in an allowed status (see constructor).<br>
     * If no Revision have a TcReleaseStatus, or if none of these statuses have a release date, or if no status is allowed, then returns the Revision with the latest last_mod_date (that is before the provided deadline).
     *
     * @param session an active {@link TcSession}
     * @param item    the {@link Item} for which we need to find a Revision
     * @return ItemRevision the most Up-to-date Revision
     */
    @Override
    public RevisionStatusAndDate selectRevision(final TcSession session, final Item item) {
        String itemID = item.get_item_id();
        String deadLineStr = deadline == null ? "no date" : TeamcenterDateFormatter.formatCalendarToPattern(deadline, "yyyy-MMM-dd");
        log.debug("START findAll correct revision for Item in pseudo-folder of an Alternate or Det {}, with date {}", itemID, deadLineStr);

        List<ItemRevision> itemsRevision = new ItemRevisionQuery(session).searchID(itemID).findAll();
        Optional<RevisionStatusAndDate> bestRevision = ObjectInfoHelper.getRevisionAndStatusWithMostRecentReleaseDate(session, itemsRevision, deadline, allowedStatuses);
        if (bestRevision.isPresent()) {
            RevisionStatusAndDate rev = bestRevision.get();
            log.debug("The highest revision of the Item {} is {}, it has the latest realease_date", itemID,
                    rev.getItemRevision().get_item_revision_id());
            return bestRevision.get();
        } else {
            RevisionStatusAndDate latestItemRev = ObjectInfoHelper.getRevisionAndStatusWithMostRecentModificationDate(itemsRevision, deadline);
            log.debug("The highest revision of the Item {} is {}, it has the latest last_mod_date", itemID, latestItemRev.getItemRevision().get_item_revision_id());
            return latestItemRev;
        }
    }
}
