package com.capgemini.reports.definition.r22report;

import com.capgemini.framework.teamcenter.authent.TcSession;
import com.capgemini.framework.teamcenter.exceptions.KurtException;
import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObject;
import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcBomObjectFactory;
import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcRevisionRule;
import com.capgemini.framework.teamcenter.object.pom.workspace.bom.TcRevisionRuleProperties;
import com.capgemini.framework.teamcenter.object.runtime.TcBomWindow;
import com.capgemini.framework.teamcenter.object.runtime.TcBomWindowConfiguration;
import com.capgemini.framework.teamcenter.object.runtime.TcRevisionRulesConfiguration;
import com.capgemini.framework.teamcenter.object.types.SnecmaObjectTypes;
import com.capgemini.framework.teamcenter.queries.saved.modelobject.ItemRevisionQuery;
import com.capgemini.reports.bomlineholder.BOMLineHolder;
import com.capgemini.reports.bomlineholder.BOMLineHolderFactory;
import com.capgemini.reports.bomlineholder.processor.DefaultAltOrDetBehaviour;
import com.capgemini.reports.definition.r22report.ExecutionR22.ReportDataR22;
import com.capgemini.reports.definition.r22report.visitors.R22Visitor;
import com.capgemini.reports.exceptions.InvalidUserInputException;
import com.capgemini.reports.exceptions.UserInputErrorEnum;
import com.capgemini.reports.execution.IDataReportPreparator;
import com.capgemini.reports.execution.strategies.IExecutionStrategy;
import com.capgemini.reports.filter.AllIsGoodFilter;
import com.capgemini.reports.printing.PrintParameters;
import com.capgemini.reports.reports.parameters.EffectivityDate;
import com.capgemini.reports.teamcenter.ObjectInfoLoader;
import com.capgemini.reports.teamcenter.resolution.structureservice.MultiStructureServiceCaller;
import com.teamcenter.soa.client.model.ModelObject;
import com.teamcenter.soa.client.model.strong.Form;
import com.teamcenter.soa.client.model.strong.ItemRevision;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

/**
 * This class will allow to prepare data and findAll back data for making report R22.
 */
class DataReportPreparatorR22 implements IDataReportPreparator<ExecutionR22> {
    private static final long serialVersionUID = 1219563840412154089L;
    private static final Logger LOGGER = LoggerFactory.getLogger(ExecutionR22.class);

    private static final AllIsGoodFilter ACCEPT_ALL = new AllIsGoodFilter();

    @Override
    public String print(TcSession session, ExecutionR22 execution, IExecutionStrategy executionStrategy) throws KurtException {
        PrintParameters printParameters = prepareData(session, execution);
        executionStrategy.print(printParameters, execution);
        return executionStrategy.getReportFileName(execution) + printParameters.getOuputFileExtension();
    }

    private PrintParameters prepareData(final TcSession session, final ExecutionR22 report) throws KurtException {
        LOGGER.debug("PrepareData started on: {}", report.getReportIdentifier().getReportTitle());

        // Obtain the top Part
        List<ItemRevision> list =
                new ItemRevisionQuery(session).searchIDAndRevision(report.getPartId(), report.getPartRevision()).findAll();
        if (list.isEmpty()) {
            throw new InvalidUserInputException(UserInputErrorEnum.OBJECT_DOES_NOT_EXIST);
        }

        ItemRevision itemRevision = null;

        for(ItemRevision currentItemRev : list) {
            if(SnecmaObjectTypes.isPartRevision(currentItemRev.getTypeObject().getName())){
                itemRevision = currentItemRev;
                break;
            }
        }

        if(itemRevision == null){
            throw new InvalidUserInputException(UserInputErrorEnum.THE_SELECTED_OBJECT_IS_NOT_PERMITTED_ON_THIS_REPORT);
        }

        TcBomObject topLineObject = new TcBomObjectFactory(session, itemRevision).create();
        EffectivityDate effectivityDate = report.getEffectivity();

        TcRevisionRuleProperties revisionRuleProperties = new TcRevisionRuleProperties(effectivityDate.isNow() ? null : effectivityDate.getDateTime());

        TcRevisionRule revisionRule = session.findRevRule(report.getRevisionRule());
        TcRevisionRulesConfiguration revRulesConfiguration = new TcRevisionRulesConfiguration(revisionRule, revisionRuleProperties);

        try (TcBomWindow bomWindow = session.createBomWindow(new TcBomWindowConfiguration(topLineObject, revRulesConfiguration))) {
            session.setObjectPropPolicy(report.getFullPolicy());

            // Obtain the clause de propriete form the ItemRevision that was fetched in the config
            String typeProduit = ObjectInfoLoader.getProductType(session, (ItemRevision) bomWindow.topLine().get_bl_line_object());
            String clausePropriete = ObjectInfoLoader.getClausePropriete(typeProduit, session);

            // Perform the job
            BOMLineHolder unbuiltTopLine = new MultiStructureServiceCaller(session).resolve(bomWindow.topLine(), ACCEPT_ALL);

            List<Form> itemRevMaster = unbuiltTopLine.getAllItemRevMasters();
            session.loadProperties(itemRevMaster.toArray(new ModelObject[itemRevMaster.size()]));
            BOMLineHolderFactory.buildTopBom(session, unbuiltTopLine, ACCEPT_ALL);

            DefaultAltOrDetBehaviour<?, ?> altOrDetBehaviour = new DefaultAltOrDetBehaviour<>(session, report.getEffectivity().getDateTime());
            unbuiltTopLine.process(altOrDetBehaviour);
            unbuiltTopLine.freeze();

            ReportDataR22 dataR22 = new ReportDataR22(clausePropriete, unbuiltTopLine);

            R22Visitor visitor = new R22Visitor();
            PrintParameters printParameters = visitor.makeMasterTemplate(report, dataR22);
            visitor.constructDataMaps(session, printParameters, dataR22);

            LOGGER.debug("PrepareData ended on: {}", report.getReportIdentifier().getReportTitle());

            return printParameters;
        }
    }
}
