/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.syncope.core.provisioning.java.pushpull;

import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.syncope.common.lib.AnyOperations;
import org.apache.syncope.common.lib.request.AnyCR;
import org.apache.syncope.common.lib.request.AnyUR;
import org.apache.syncope.common.lib.request.StringPatchItem;
import org.apache.syncope.common.lib.to.AnyTO;
import org.apache.syncope.common.lib.to.ProvisioningReport;
import org.apache.syncope.common.lib.types.AnyTypeKind;
import org.apache.syncope.common.lib.types.AuditElements;
import org.apache.syncope.common.lib.types.AuditElements.Result;
import org.apache.syncope.common.lib.types.MatchType;
import org.apache.syncope.common.lib.types.MatchingRule;
import org.apache.syncope.common.lib.types.PatchOperation;
import org.apache.syncope.common.lib.types.PullMode;
import org.apache.syncope.common.lib.types.ResourceOperation;
import org.apache.syncope.common.lib.types.TaskType;
import org.apache.syncope.common.lib.types.UnmatchingRule;
import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
import org.apache.syncope.core.persistence.api.dao.NotFoundException;
import org.apache.syncope.core.persistence.api.dao.PullMatch;
import org.apache.syncope.core.persistence.api.dao.RemediationDAO;
import org.apache.syncope.core.persistence.api.dao.TaskDAO;
import org.apache.syncope.core.persistence.api.dao.UserDAO;
import org.apache.syncope.core.persistence.api.dao.VirSchemaDAO;
import org.apache.syncope.core.persistence.api.entity.AnyType;
import org.apache.syncope.core.persistence.api.entity.EntityFactory;
import org.apache.syncope.core.persistence.api.entity.Remediation;
import org.apache.syncope.core.persistence.api.entity.resource.Provision;
import org.apache.syncope.core.persistence.api.entity.task.PullTask;
import org.apache.syncope.core.provisioning.api.AuditManager;
import org.apache.syncope.core.provisioning.api.PropagationByResource;
import org.apache.syncope.core.provisioning.api.ProvisioningManager;
import org.apache.syncope.core.provisioning.api.cache.VirAttrCache;
import org.apache.syncope.core.provisioning.api.cache.VirAttrCacheKey;
import org.apache.syncope.core.provisioning.api.cache.VirAttrCacheValue;
import org.apache.syncope.core.provisioning.api.notification.NotificationManager;
import org.apache.syncope.core.provisioning.api.propagation.PropagationException;
import org.apache.syncope.core.provisioning.api.pushpull.IgnoreProvisionException;
import org.apache.syncope.core.provisioning.api.pushpull.PullActions;
import org.apache.syncope.core.provisioning.api.pushpull.SyncopePullExecutor;
import org.apache.syncope.core.provisioning.api.pushpull.SyncopePullResultHandler;
import org.apache.syncope.core.provisioning.java.utils.ConnObjectUtils;
import org.apache.syncope.core.spring.security.DelegatedAdministrationException;
import org.identityconnectors.framework.common.objects.Attribute;
import org.identityconnectors.framework.common.objects.SyncDelta;
import org.identityconnectors.framework.common.objects.SyncDeltaType;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

@Transactional(rollbackFor = Throwable.class)
public abstract class AbstractPullResultHandler extends AbstractSyncopeResultHandler<PullTask, PullActions>
        implements SyncopePullResultHandler {

    @Autowired
    protected InboundMatcher inboundMatcher;

    @Autowired
    protected NotificationManager notificationManager;

    @Autowired
    protected AuditManager auditManager;

    @Autowired
    protected ConnObjectUtils connObjectUtils;

    @Autowired
    protected UserDAO userDAO;

    @Autowired
    protected AnyTypeDAO anyTypeDAO;

    @Autowired
    protected TaskDAO taskDAO;

    @Autowired
    protected RemediationDAO remediationDAO;

    @Autowired
    protected VirSchemaDAO virSchemaDAO;

    @Autowired
    protected VirAttrCache virAttrCache;

    @Autowired
    protected EntityFactory entityFactory;

    protected SyncopePullExecutor executor;

    protected Result latestResult;

    protected abstract String getName(AnyTO anyTO);

    protected abstract String getName(AnyCR anyCR);

    protected abstract ProvisioningManager<?, ?> getProvisioningManager();

    protected abstract AnyTO doCreate(AnyCR anyCR, SyncDelta delta);

    protected abstract AnyUR doUpdate(AnyTO before, AnyUR anyUR, SyncDelta delta, ProvisioningReport result);

    @Override
    public void setPullExecutor(final SyncopePullExecutor executor) {
        this.executor = executor;
    }

    @Override
    public boolean handle(final SyncDelta delta) {
        Provision provision = null;
        try {
            provision = profile.getTask().getResource().getProvision(delta.getObject().getObjectClass()).
                    orElseThrow(() -> new JobExecutionException(
                    "No provision found on " + profile.getTask().getResource()
                    + " for " + delta.getObject().getObjectClass()));

            doHandle(delta, provision);
            executor.reportHandled(delta.getObjectClass(), delta.getObject().getName());

            LOG.debug("Successfully handled {}", delta);

            if (profile.getTask().getPullMode() != PullMode.INCREMENTAL) {
                if (executor.wasInterruptRequested()) {
                    LOG.debug("Pull interrupted");
                    executor.setInterrupted();
                    return false;
                }
                return true;
            }

            boolean shouldContinue;
            synchronized (this) {
                shouldContinue = latestResult == Result.SUCCESS;
                this.latestResult = null;
            }
            if (shouldContinue) {
                executor.setLatestSyncToken(delta.getObjectClass(), delta.getToken());
            }
            if (executor.wasInterruptRequested()) {
                LOG.debug("Pull interrupted");
                executor.setInterrupted();
                return false;
            }
            return shouldContinue;
        } catch (IgnoreProvisionException e) {
            ProvisioningReport ignoreResult = new ProvisioningReport();
            ignoreResult.setOperation(ResourceOperation.NONE);
            ignoreResult.setAnyType(provision == null
                    ? getAnyUtils().anyTypeKind().name() : provision.getAnyType().getKey());
            ignoreResult.setStatus(ProvisioningReport.Status.IGNORE);
            ignoreResult.setMessage(e.getMessage());
            ignoreResult.setKey(null);
            ignoreResult.setUidValue(delta.getUid().getUidValue());
            ignoreResult.setName(delta.getObject().getName().getNameValue());
            profile.getResults().add(ignoreResult);

            LOG.warn("Ignoring during pull", e);

            executor.setLatestSyncToken(delta.getObjectClass(), delta.getToken());
            executor.reportHandled(delta.getObjectClass(), delta.getObject().getName());

            return true;
        } catch (JobExecutionException e) {
            LOG.error("Pull failed", e);

            return false;
        }
    }

    protected List<ProvisioningReport> provision(
            final UnmatchingRule rule,
            final SyncDelta delta,
            final Provision provision) throws JobExecutionException {

        if (!profile.getTask().isPerformCreate()) {
            LOG.debug("PullTask not configured for create");
            end(provision.getAnyType().getKind(), UnmatchingRule.toEventName(rule), Result.SUCCESS, null, null, delta);
            return List.of();
        }

        AnyCR anyCR = connObjectUtils.getAnyCR(delta.getObject(), profile.getTask(), provision, true);
        if (rule == UnmatchingRule.ASSIGN) {
            anyCR.getResources().add(profile.getTask().getResource().getKey());
        }

        ProvisioningReport result = new ProvisioningReport();
        result.setOperation(ResourceOperation.CREATE);
        result.setAnyType(provision.getAnyType().getKey());
        result.setStatus(ProvisioningReport.Status.SUCCESS);
        result.setName(getName(anyCR));
        result.setUidValue(delta.getUid().getUidValue());

        if (profile.isDryRun()) {
            result.setKey(null);
            end(provision.getAnyType().getKind(), UnmatchingRule.toEventName(rule), Result.SUCCESS, null, null, delta);
        } else {
            Object output;
            Result resultStatus;
            try {
                for (PullActions action : profile.getActions()) {
                    if (rule == UnmatchingRule.ASSIGN) {
                        action.beforeAssign(profile, delta, anyCR);
                    } else if (rule == UnmatchingRule.PROVISION) {
                        action.beforeProvision(profile, delta, anyCR);
                    }
                }
                result.setName(getName(anyCR));

                AnyTO created = doCreate(anyCR, delta);
                output = created;
                result.setKey(created.getKey());
                result.setName(getName(created));
                resultStatus = Result.SUCCESS;

                for (PullActions action : profile.getActions()) {
                    action.after(profile, delta, created, result);
                }

                LOG.debug("{} {} successfully created", created.getType(), created.getKey());
            } catch (PropagationException e) {
                // A propagation failure doesn't imply a pull failure.
                // The propagation exception status will be reported into the propagation task execution.
                LOG.error("Could not propagate {} {}",
                        provision.getAnyType().getKey(), delta.getUid().getUidValue(), e);
                output = e;
                resultStatus = Result.FAILURE;
            } catch (Exception e) {
                throwIgnoreProvisionException(delta, e);

                result.setStatus(ProvisioningReport.Status.FAILURE);
                result.setMessage(ExceptionUtils.getRootCauseMessage(e));
                LOG.error("Could not create {} {} ", provision.getAnyType().getKey(), delta.getUid().getUidValue(), e);
                output = e;

                if (profile.getTask().isRemediation()) {
                    // set to SUCCESS to let the incremental flow go on in case of errors
                    resultStatus = Result.SUCCESS;
                    createRemediation(
                            provision.getAnyType(),
                            null,
                            anyCR,
                            null,
                            taskDAO.exists(TaskType.PULL, profile.getTask().getKey())
                            ? profile.getTask() : null,
                            result,
                            delta);
                } else {
                    resultStatus = Result.FAILURE;
                }
            }

            end(provision.getAnyType().getKind(), UnmatchingRule.toEventName(rule), resultStatus, null, output, delta);
        }

        return List.of(result);
    }

    protected void throwIgnoreProvisionException(final SyncDelta delta, final Exception exception)
            throws JobExecutionException {

        if (exception instanceof IgnoreProvisionException) {
            throw IgnoreProvisionException.class.cast(exception);
        }

        IgnoreProvisionException ipe = null;
        for (PullActions action : profile.getActions()) {
            if (ipe == null) {
                ipe = action.onError(profile, delta, exception);
            }
        }
        if (ipe != null) {
            throw ipe;
        }
    }

    protected List<ProvisioningReport> update(
            final SyncDelta delta,
            final List<PullMatch> matches,
            final Provision provision) throws JobExecutionException {

        if (!profile.getTask().isPerformUpdate()) {
            LOG.debug("PullTask not configured for update");
            end(provision.getAnyType().getKind(),
                    MatchingRule.toEventName(MatchingRule.UPDATE), Result.SUCCESS, null, null, delta);
            return List.of();
        }

        LOG.debug("About to update {}", matches);

        List<ProvisioningReport> results = new ArrayList<>();

        for (PullMatch match : matches) {
            LOG.debug("About to update {}", match);

            ProvisioningReport result = new ProvisioningReport();
            result.setOperation(ResourceOperation.UPDATE);
            result.setAnyType(provision.getAnyType().getKey());
            result.setStatus(ProvisioningReport.Status.SUCCESS);
            result.setKey(match.getAny().getKey());
            result.setUidValue(delta.getUid().getUidValue());

            AnyTO before = getAnyTO(match.getAny());
            if (before == null) {
                result.setStatus(ProvisioningReport.Status.FAILURE);
                result.setMessage(String.format("Any '%s(%s)' not found", provision.getAnyType().getKey(), match));
            } else {
                result.setName(getName(before));
            }

            if (!profile.isDryRun()) {
                Result resultStatus;
                Object output;
                AnyUR effectiveReq = null;

                if (before == null) {
                    resultStatus = Result.FAILURE;
                    output = null;
                } else {
                    AnyUR anyUR = null;
                    try {
                        anyUR = connObjectUtils.getAnyUR(
                                before.getKey(),
                                delta.getObject(),
                                before,
                                profile.getTask(),
                                provision);

                        for (PullActions action : profile.getActions()) {
                            action.beforeUpdate(profile, delta, before, anyUR);
                        }

                        effectiveReq = doUpdate(before, anyUR, delta, result);
                        AnyTO updated = AnyOperations.patch(before, effectiveReq);

                        for (PullActions action : profile.getActions()) {
                            action.after(profile, delta, updated, result);
                        }

                        output = updated;
                        resultStatus = Result.SUCCESS;
                        result.setName(getName(updated));

                        LOG.debug("{} {} successfully updated", provision.getAnyType().getKey(), match);
                    } catch (PropagationException e) {
                        // A propagation failure doesn't imply a pull failure.
                        // The propagation exception status will be reported into the propagation task execution.
                        LOG.error("Could not propagate {} {}",
                                provision.getAnyType().getKey(), delta.getUid().getUidValue(), e);
                        output = e;
                        resultStatus = Result.FAILURE;
                    } catch (Exception e) {
                        throwIgnoreProvisionException(delta, e);

                        result.setStatus(ProvisioningReport.Status.FAILURE);
                        result.setMessage(ExceptionUtils.getRootCauseMessage(e));
                        LOG.error("Could not update {} {}",
                                provision.getAnyType().getKey(), delta.getUid().getUidValue(), e);
                        output = e;

                        if (profile.getTask().isRemediation()) {
                            // set to SUCCESS to let the incremental flow go on in case of errors
                            resultStatus = Result.SUCCESS;
                            createRemediation(
                                    provision.getAnyType(),
                                    anyUR,
                                    taskDAO.exists(TaskType.PULL, profile.getTask().getKey())
                                    ? profile.getTask() : null,
                                    result,
                                    delta);
                        } else {
                            resultStatus = Result.FAILURE;
                        }
                    }
                }
                end(provision.getAnyType().getKind(),
                        MatchingRule.toEventName(MatchingRule.UPDATE),
                        resultStatus, before, output, delta, effectiveReq);
            }
            results.add(result);
        }
        return results;
    }

    protected List<ProvisioningReport> deprovision(
            final MatchingRule matchingRule,
            final SyncDelta delta,
            final List<PullMatch> matches,
            final Provision provision)
            throws JobExecutionException {

        if (!profile.getTask().isPerformUpdate()) {
            LOG.debug("PullTask not configured for update");
            end(provision.getAnyType().getKind(),
                    MatchingRule.toEventName(matchingRule), Result.SUCCESS, null, null, delta);
            return List.of();
        }

        LOG.debug("About to deprovision {}", matches);

        List<ProvisioningReport> results = new ArrayList<>();

        for (PullMatch match : matches) {
            LOG.debug("About to unassign resource {}", match);

            ProvisioningReport result = new ProvisioningReport();
            result.setOperation(ResourceOperation.DELETE);
            result.setAnyType(provision.getAnyType().getKey());
            result.setStatus(ProvisioningReport.Status.SUCCESS);
            result.setKey(match.getAny().getKey());
            result.setUidValue(delta.getUid().getUidValue());

            AnyTO before = getAnyTO(match.getAny());

            if (before == null) {
                result.setStatus(ProvisioningReport.Status.FAILURE);
                result.setMessage(String.format("Any '%s(%s)' not found", provision.getAnyType().getKey(), match));
            }

            if (!profile.isDryRun()) {
                Object output;
                Result resultStatus;

                if (before == null) {
                    resultStatus = Result.FAILURE;
                    output = null;
                } else {
                    result.setName(getName(before));

                    try {
                        if (matchingRule == MatchingRule.UNASSIGN) {
                            for (PullActions action : profile.getActions()) {
                                action.beforeUnassign(profile, delta, before);
                            }
                        } else if (matchingRule == MatchingRule.DEPROVISION) {
                            for (PullActions action : profile.getActions()) {
                                action.beforeDeprovision(profile, delta, before);
                            }
                        }

                        PropagationByResource<String> propByRes = new PropagationByResource<>();
                        propByRes.add(ResourceOperation.DELETE, provision.getResource().getKey());

                        taskExecutor.execute(propagationManager.getDeleteTasks(
                                provision.getAnyType().getKind(),
                                match.getAny().getKey(),
                                propByRes,
                                null,
                                null),
                                false,
                                securityProperties.getAdminUser());

                        AnyUR anyUR = null;
                        if (matchingRule == MatchingRule.UNASSIGN) {
                            anyUR = getAnyUtils().newAnyUR(match.getAny().getKey());
                            anyUR.getResources().add(new StringPatchItem.Builder().
                                    operation(PatchOperation.DELETE).
                                    value(profile.getTask().getResource().getKey()).build());
                        }
                        if (anyUR == null) {
                            output = getAnyTO(match.getAny());
                        } else {
                            output = doUpdate(before, anyUR, delta, result);
                        }

                        for (PullActions action : profile.getActions()) {
                            action.after(profile, delta, AnyTO.class.cast(output), result);
                        }

                        resultStatus = Result.SUCCESS;

                        LOG.debug("{} {} successfully updated", provision.getAnyType().getKey(), match);
                    } catch (PropagationException e) {
                        // A propagation failure doesn't imply a pull failure.
                        // The propagation exception status will be reported into the propagation task execution.
                        LOG.error("Could not propagate {} {}",
                                provision.getAnyType().getKey(), delta.getUid().getUidValue(), e);
                        output = e;
                        resultStatus = Result.FAILURE;
                    } catch (Exception e) {
                        throwIgnoreProvisionException(delta, e);

                        result.setStatus(ProvisioningReport.Status.FAILURE);
                        result.setMessage(ExceptionUtils.getRootCauseMessage(e));
                        LOG.error("Could not update {} {}",
                                provision.getAnyType().getKey(), delta.getUid().getUidValue(), e);
                        output = e;
                        resultStatus = Result.FAILURE;
                    }
                }
                end(provision.getAnyType().getKind(),
                        MatchingRule.toEventName(matchingRule), resultStatus, before, output, delta);
            }
            results.add(result);
        }

        return results;
    }

    protected List<ProvisioningReport> link(
            final SyncDelta delta,
            final List<PullMatch> matches,
            final Provision provision,
            final boolean unlink)
            throws JobExecutionException {

        if (!profile.getTask().isPerformUpdate()) {
            LOG.debug("PullTask not configured for update");
            end(provision.getAnyType().getKind(),
                    unlink
                            ? MatchingRule.toEventName(MatchingRule.UNLINK)
                            : MatchingRule.toEventName(MatchingRule.LINK),
                    Result.SUCCESS, null, null, delta);
            return List.of();
        }

        LOG.debug("About to update {}", matches);

        final List<ProvisioningReport> results = new ArrayList<>();

        for (PullMatch match : matches) {
            LOG.debug("About to unassign resource {}", match);

            ProvisioningReport result = new ProvisioningReport();
            result.setOperation(ResourceOperation.NONE);
            result.setAnyType(provision.getAnyType().getKey());
            result.setStatus(ProvisioningReport.Status.SUCCESS);
            result.setKey(match.getAny().getKey());
            result.setUidValue(delta.getUid().getUidValue());

            AnyTO before = getAnyTO(match.getAny());

            if (before == null) {
                result.setStatus(ProvisioningReport.Status.FAILURE);
                result.setMessage(String.format("Any '%s(%s)' not found", provision.getAnyType().getKey(), match));
            }

            if (!profile.isDryRun()) {
                Result resultStatus;
                Object output;
                AnyUR effectiveReq = null;

                if (before == null) {
                    resultStatus = Result.FAILURE;
                    output = null;
                } else {
                    result.setName(getName(before));

                    try {
                        if (unlink) {
                            for (PullActions action : profile.getActions()) {
                                action.beforeUnlink(profile, delta, before);
                            }
                        } else {
                            for (PullActions action : profile.getActions()) {
                                action.beforeLink(profile, delta, before);
                            }
                        }

                        AnyUR anyUR = getAnyUtils().newAnyUR(before.getKey());
                        anyUR.getResources().add(new StringPatchItem.Builder().
                                operation(unlink ? PatchOperation.DELETE : PatchOperation.ADD_REPLACE).
                                value(profile.getTask().getResource().getKey()).build());

                        effectiveReq = update(anyUR).getResult();
                        output = AnyOperations.patch(before, effectiveReq);

                        for (PullActions action : profile.getActions()) {
                            action.after(profile, delta, AnyTO.class.cast(output), result);
                        }

                        resultStatus = Result.SUCCESS;

                        LOG.debug("{} {} successfully updated", provision.getAnyType().getKey(), match);
                    } catch (PropagationException e) {
                        // A propagation failure doesn't imply a pull failure.
                        // The propagation exception status will be reported into the propagation task execution.
                        LOG.error("Could not propagate {} {}",
                                provision.getAnyType().getKey(), delta.getUid().getUidValue(), e);
                        output = e;
                        resultStatus = Result.FAILURE;
                    } catch (Exception e) {
                        throwIgnoreProvisionException(delta, e);

                        result.setStatus(ProvisioningReport.Status.FAILURE);
                        result.setMessage(ExceptionUtils.getRootCauseMessage(e));
                        LOG.error("Could not update {} {}",
                                provision.getAnyType().getKey(), delta.getUid().getUidValue(), e);
                        output = e;
                        resultStatus = Result.FAILURE;
                    }
                }
                end(provision.getAnyType().getKind(),
                        unlink
                                ? MatchingRule.toEventName(MatchingRule.UNLINK)
                                : MatchingRule.toEventName(MatchingRule.LINK),
                        resultStatus, before, output, delta, effectiveReq);
            }
            results.add(result);
        }

        return results;
    }

    protected List<ProvisioningReport> delete(
            final SyncDelta delta,
            final List<PullMatch> matches,
            final Provision provision)
            throws JobExecutionException {

        if (!profile.getTask().isPerformDelete()) {
            LOG.debug("PullTask not configured for delete");
            end(provision.getAnyType().getKind(),
                    ResourceOperation.DELETE.name().toLowerCase(), Result.SUCCESS, null, null, delta);
            return List.of();
        }

        LOG.debug("About to delete {}", matches);

        List<ProvisioningReport> results = new ArrayList<>();

        matches.forEach(match -> {
            Object output;
            Result resultStatus = Result.FAILURE;

            ProvisioningReport result = new ProvisioningReport();

            try {
                AnyTO before = getAnyTO(match.getAny());

                result.setKey(match.getAny().getKey());
                result.setName(getName(before));
                result.setOperation(ResourceOperation.DELETE);
                result.setAnyType(provision.getAnyType().getKey());
                result.setStatus(ProvisioningReport.Status.SUCCESS);
                result.setUidValue(delta.getUid().getUidValue());

                if (!profile.isDryRun()) {
                    for (PullActions action : profile.getActions()) {
                        action.beforeDelete(profile, delta, before);
                    }

                    try {
                        getProvisioningManager().delete(
                                match.getAny().getKey(),
                                Set.of(profile.getTask().getResource().getKey()),
                                true,
                                profile.getExecutor(),
                                getContext());
                        output = null;
                        resultStatus = Result.SUCCESS;

                        for (PullActions action : profile.getActions()) {
                            action.after(profile, delta, before, result);
                        }
                    } catch (Exception e) {
                        throwIgnoreProvisionException(delta, e);

                        result.setStatus(ProvisioningReport.Status.FAILURE);
                        result.setMessage(ExceptionUtils.getRootCauseMessage(e));
                        LOG.error("Could not delete {} {}", provision.getAnyType().getKey(), match, e);
                        output = e;

                        if (profile.getTask().isRemediation()) {
                            // set to SUCCESS to let the incremental flow go on in case of errors
                            resultStatus = Result.SUCCESS;
                            createRemediation(
                                    provision.getAnyType(),
                                    match.getAny().getKey(),
                                    null,
                                    null,
                                    taskDAO.exists(TaskType.PULL, profile.getTask().getKey())
                                    ? profile.getTask() : null,
                                    result,
                                    delta);
                        }
                    }

                    end(provision.getAnyType().getKind(),
                            ResourceOperation.DELETE.name().toLowerCase(), resultStatus, before, output, delta);
                }

                results.add(result);
            } catch (NotFoundException e) {
                LOG.error("Could not find {} {}", provision.getAnyType().getKey(), match, e);
            } catch (DelegatedAdministrationException e) {
                LOG.error("Not allowed to read {} {}", provision.getAnyType().getKey(), match, e);
            } catch (Exception e) {
                LOG.error("Could not delete {} {}", provision.getAnyType().getKey(), match, e);
            }
        });

        return results;
    }

    protected List<ProvisioningReport> ignore(
            final SyncDelta delta,
            final List<PullMatch> matches,
            final Provision provision,
            final boolean matching,
            final String... message)
            throws JobExecutionException {

        LOG.debug("Any to ignore {}", delta.getObject().getUid().getUidValue());

        List<ProvisioningReport> results = new ArrayList<>();

        if (matches == null) {
            ProvisioningReport report = new ProvisioningReport();
            report.setKey(null);
            report.setName(delta.getObject().getUid().getUidValue());
            report.setOperation(ResourceOperation.NONE);
            report.setAnyType(provision.getAnyType().getKey());
            report.setStatus(ProvisioningReport.Status.SUCCESS);
            report.setUidValue(delta.getUid().getUidValue());
            if (message != null && message.length >= 1) {
                report.setMessage(message[0]);
            }

            results.add(report);
        } else {
            matches.forEach(match -> {
                ProvisioningReport report = new ProvisioningReport();
                report.setKey(match.getAny().getKey());
                report.setName(delta.getObject().getUid().getUidValue());
                report.setOperation(ResourceOperation.NONE);
                report.setAnyType(provision.getAnyType().getKey());
                report.setStatus(ProvisioningReport.Status.SUCCESS);
                report.setUidValue(delta.getUid().getUidValue());
                if (message != null && message.length >= 1) {
                    report.setMessage(message[0]);
                }

                results.add(report);
            });
        }

        end(provision.getAnyType().getKind(),
                matching
                        ? MatchingRule.toEventName(MatchingRule.IGNORE)
                        : UnmatchingRule.toEventName(UnmatchingRule.IGNORE), Result.SUCCESS, null, null, delta);

        return results;
    }

    protected void handleAnys(
            final SyncDelta delta,
            final List<PullMatch> matches,
            final Provision provision) throws JobExecutionException {

        if (matches.isEmpty()) {
            LOG.debug("Nothing to do");
            return;
        }

        if (SyncDeltaType.CREATE_OR_UPDATE == delta.getDeltaType()) {
            if (matches.get(0).getAny() == null) {
                switch (profile.getTask().getUnmatchingRule()) {
                    case ASSIGN:
                    case PROVISION:
                        profile.getResults().addAll(
                                provision(profile.getTask().getUnmatchingRule(), delta, provision));
                        break;

                    case IGNORE:
                        profile.getResults().addAll(ignore(delta, null, provision, false));
                        break;

                    default:
                    // do nothing
                    }
            } else {
                // update VirAttrCache
                virSchemaDAO.findByProvision(provision).forEach(schema -> {
                    Attribute attr = delta.getObject().getAttributeByName(schema.getExtAttrName());
                    matches.forEach(match -> {
                        VirAttrCacheKey cacheKey = new VirAttrCacheKey(
                                provision.getAnyType().getKey(), match.getAny().getKey(),
                                schema.getKey());
                        if (attr == null) {
                            virAttrCache.expire(cacheKey);
                        } else {
                            virAttrCache.put(cacheKey, new VirAttrCacheValue(attr.getValue()));
                        }
                    });
                });

                switch (profile.getTask().getMatchingRule()) {
                    case UPDATE:
                        profile.getResults().addAll(update(delta, matches, provision));
                        break;

                    case DEPROVISION:
                    case UNASSIGN:
                        profile.getResults().addAll(
                                deprovision(profile.getTask().getMatchingRule(), delta, matches, provision));
                        break;

                    case LINK:
                        profile.getResults().addAll(link(delta, matches, provision, false));
                        break;

                    case UNLINK:
                        profile.getResults().addAll(link(delta, matches, provision, true));
                        break;

                    case IGNORE:
                        profile.getResults().addAll(ignore(delta, matches, provision, true));
                        break;

                    default:
                    // do nothing
                    }
            }
        } else if (SyncDeltaType.DELETE == delta.getDeltaType()) {
            profile.getResults().addAll(delete(delta, matches, provision));
        }
    }

    protected void handleLinkedAccounts(
            final SyncDelta delta,
            final List<PullMatch> matches,
            final Provision provision) throws JobExecutionException {

        if (matches.isEmpty()) {
            LOG.debug("Nothing to do");
            return;
        }

        // nothing to do in the general case
        LOG.warn("Unexpected linked accounts found for {}: {}", provision.getAnyType().getKind(), matches);
    }

    /**
     * Look into SyncDelta and take necessary profile.getActions() (create / update / delete) on any object(s).
     *
     * @param delta returned by the underlying profile.getConnector()
     * @param provision provisioning info
     * @throws JobExecutionException in case of pull failure.
     */
    protected void doHandle(final SyncDelta delta, final Provision provision) throws JobExecutionException {
        LOG.debug("Process {} for {} as {}",
                delta.getDeltaType(), delta.getUid().getUidValue(), delta.getObject().getObjectClass());

        SyncDelta finalDelta = delta;
        for (PullActions action : profile.getActions()) {
            finalDelta = action.preprocess(profile, finalDelta);
        }

        LOG.debug("Transformed {} for {} as {}",
                finalDelta.getDeltaType(), finalDelta.getUid().getUidValue(), finalDelta.getObject().getObjectClass());

        try {
            List<PullMatch> matches = inboundMatcher.match(finalDelta, provision);
            LOG.debug("Match(es) found for {} as {}: {}",
                    finalDelta.getUid().getUidValue(), finalDelta.getObject().getObjectClass(), matches);

            if (matches.size() > 1) {
                switch (profile.getConflictResolutionAction()) {
                    case IGNORE:
                        throw new IgnoreProvisionException("More than one match found for "
                                + finalDelta.getObject().getUid().getUidValue() + ": " + matches);

                    case FIRSTMATCH:
                        matches = matches.subList(0, 1);
                        break;

                    case LASTMATCH:
                        matches = matches.subList(matches.size() - 1, matches.size());
                        break;

                    default:
                    // keep matches unmodified
                }
            }

            // users, groups and any objects
            handleAnys(
                    finalDelta,
                    matches.stream().
                            filter(match -> match.getMatchTarget() == MatchType.ANY).
                            collect(Collectors.toList()), provision);

            // linked accounts
            handleLinkedAccounts(
                    finalDelta,
                    matches.stream().
                            filter(match -> match.getMatchTarget() == MatchType.LINKED_ACCOUNT).
                            collect(Collectors.toList()), provision);
        } catch (IllegalStateException | IllegalArgumentException e) {
            LOG.warn(e.getMessage());
        }
    }

    protected void end(
            final AnyTypeKind anyTypeKind,
            final String event,
            final Result result,
            final Object before,
            final Object output,
            final SyncDelta delta,
            final Object... furtherInput) {

        synchronized (this) {
            this.latestResult = result;
        }

        notificationManager.createTasks(
                profile.getExecutor(),
                AuditElements.EventCategoryType.PULL,
                anyTypeKind.name().toLowerCase(),
                profile.getTask().getResource().getKey(),
                event,
                result,
                before,
                output,
                delta,
                furtherInput);

        auditManager.audit(
                profile.getExecutor(),
                AuditElements.EventCategoryType.PULL,
                anyTypeKind.name().toLowerCase(),
                profile.getTask().getResource().getKey(),
                event,
                result,
                before,
                output,
                delta,
                furtherInput);
    }

    protected void createRemediationIfNeeded(
            final AnyUR anyUR,
            final SyncDelta delta,
            final ProvisioningReport result) {

        if (ProvisioningReport.Status.FAILURE == result.getStatus() && profile.getTask().isRemediation()) {
            createRemediation(
                    anyTypeDAO.find(result.getAnyType()),
                    null,
                    null,
                    anyUR,
                    taskDAO.exists(TaskType.PULL, profile.getTask().getKey()) ? profile.getTask() : null,
                    result,
                    delta);
        }
    }

    protected void createRemediation(
            final AnyType anyType,
            final AnyCR anyCR,
            final PullTask pullTask,
            final ProvisioningReport result,
            final SyncDelta delta) {

        createRemediation(anyType, null, anyCR, null, pullTask, result, delta);
    }

    protected void createRemediation(
            final AnyType anyType,
            final AnyUR anyUR,
            final PullTask pullTask,
            final ProvisioningReport result,
            final SyncDelta delta) {

        createRemediation(anyType, null, null, anyUR, pullTask, result, delta);
    }

    protected void createRemediation(
            final AnyType anyType,
            final String anyKey,
            final AnyCR anyCR,
            final AnyUR anyUR,
            final PullTask pullTask,
            final ProvisioningReport result,
            final SyncDelta delta) {

        Remediation remediation = entityFactory.newEntity(Remediation.class);

        remediation.setAnyType(anyType);
        remediation.setOperation(anyUR == null ? ResourceOperation.CREATE : ResourceOperation.UPDATE);
        if (StringUtils.isNotBlank(anyKey)) {
            remediation.setPayload(anyKey);
        } else if (anyCR != null) {
            remediation.setPayload(anyCR);
        } else if (anyUR != null) {
            remediation.setPayload(anyUR);
        }
        remediation.setError(result.getMessage());
        remediation.setInstant(OffsetDateTime.now());
        remediation.setRemoteName(delta.getObject().getName().getNameValue());
        remediation.setPullTask(pullTask);

        remediation = remediationDAO.save(remediation);

        ProvisioningReport remediationResult = new ProvisioningReport();
        remediationResult.setOperation(remediation.getOperation());
        remediationResult.setAnyType(anyType.getKey());
        remediationResult.setStatus(ProvisioningReport.Status.FAILURE);
        remediationResult.setMessage(remediation.getError());
        if (StringUtils.isNotBlank(anyKey)) {
            remediationResult.setKey(anyKey);
        } else if (anyUR != null) {
            remediationResult.setKey(anyUR.getKey());
        }
        remediationResult.setUidValue(delta.getUid().getUidValue());
        remediationResult.setName(remediation.getRemoteName());
        profile.getResults().add(remediationResult);
    }
}
