package com.capgemini.reports.definition.r13report.datapreparator;

import com.capgemini.framework.teamcenter.authent.TcSession;
import com.capgemini.framework.teamcenter.exceptions.KurtException;
import com.capgemini.framework.teamcenter.queries.saved.AbstractReplicatedQuery;
import com.capgemini.framework.teamcenter.resolution.filtering.TcTypeExclusionFilter;
import com.capgemini.reports.ItemRevisionComparator;
import com.capgemini.reports.changeobjects.change.FPPRevision;
import com.capgemini.reports.definition.r13report.execution.ExecutionR13FPP;
import com.capgemini.reports.definition.r13report.printer.R13PrinterFPP;
import com.capgemini.reports.execution.IDataReportPreparator;
import com.capgemini.reports.printing.PrintParameters;
import com.capgemini.reports.teamcenter.queries.saved.FppWithSeqQuery;
import com.capgemini.reports.teamcenter.queries.saved.WorkflowOnChangeQuery;
import com.capgemini.reports.workflows.Task.TaskState;
import com.teamcenter.soa.client.model.strong.EPMTask;
import com.teamcenter.soa.client.model.strong.ItemRevision;

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

/**
 * This class will allow to prepare data and findAll back data for making report R13FPP.
 */
public class DataReportPreparatorR13FPP extends AbstractDataReportPreparatorR13<ExecutionR13FPP> implements IDataReportPreparator<ExecutionR13FPP> {
    private static final long serialVersionUID = -5070390508126458855L;

    // Configuration
    private static final String PB_REPORT_APPROVED = "Pb Report Approved";
    private static final String REFUSED = "Refused";
    private static final String CANCELLED = "Cancelled";

    @Override
    protected boolean validateStatusByName(final String statusName) {
        return new TcTypeExclusionFilter(PB_REPORT_APPROVED, REFUSED, CANCELLED).isIncluded(statusName);
    }

    @Override
    protected boolean specificValidation(final TcSession session, final ItemRevision itemRev) {
        String itemID = itemRev.get_item_id();
        String revisionID = itemRev.get_item_revision_id();
        List<EPMTask> wkfList = new WorkflowOnChangeQuery(session).searchIDAndRevision(itemID, revisionID)
                .searchSequenceId(String.valueOf(itemRev.get_sequence_id())).findAll();

        // 1st case : wkf list is empty, it must appear in the report
        if (wkfList.isEmpty()) {
            return true; // Keep this CR
        }

        // Remove finished wkf
        List<EPMTask> wkfToRemove = new ArrayList<>();
        for (EPMTask wkf : wkfList) {
            if (TaskState.COMPLETED.matches(wkf.get_state())) {
                wkfToRemove.add(wkf);
            }
        }
        wkfList.removeAll(wkfToRemove);

        // 2rd case : all the wkf are finished
        if (wkfList.isEmpty()) {
            return false; // Discard this CR
        }

        // 3rd case : at least 1 wkf is active
        return true; // Keep this CR
    }

    @Override
    protected PrintParameters buildValidatedChangeObjects(final TcSession session, final ExecutionR13FPP report) throws KurtException {
        AbstractReplicatedQuery<ItemRevision, ?> query = new FppWithSeqQuery(session);
        addParamPeriod(query, report);
        List<FPPRevision> data = new ArrayList<>();
        for (ItemRevision itemRev : validateChangeObjects(query.searchAllObjects().findAll(), session)) {
            data.add(new FPPRevision(session, itemRev));
        }

        R13PrinterFPP printer = new R13PrinterFPP();
        PrintParameters printParameters = printer.makeMasterTemplate(report, data);
        printer.constructDataMaps(session, printParameters, data);

        return printParameters;
    }

    private List<ItemRevision> validateChangeObjects(final List<ItemRevision> objects, final TcSession session) {
        List<ItemRevision> validatedObjects = new ArrayList<>();
        Collections.sort(objects, new ItemRevisionComparator());
        for (ItemRevision itemRev : objects) {
            if (itemRev == null) {
                continue;
            }
            // Common treatment on status
            if (!isStatusValid(session, itemRev)) {
                continue;
            }
            // Specific treatment if required (FPP)
            if (!specificValidation(session, itemRev)) {
                continue;
            }
            validatedObjects.add(itemRev);
        }

        return validatedObjects;
    }
}
