/*
 * 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.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Stream;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.syncope.common.lib.types.AnyTypeKind;
import org.apache.syncope.core.persistence.api.dao.PushCorrelationRule;
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.Any;
import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
import org.apache.syncope.core.persistence.api.entity.LinkingMappingItem;
import org.apache.syncope.core.persistence.api.entity.VirSchema;
import org.apache.syncope.core.persistence.api.entity.policy.PushCorrelationRuleEntity;
import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
import org.apache.syncope.core.persistence.api.entity.resource.Provision;
import org.apache.syncope.core.persistence.api.entity.task.PropagationTask;
import org.apache.syncope.core.provisioning.api.Connector;
import org.apache.syncope.core.provisioning.api.MappingManager;
import org.apache.syncope.core.provisioning.api.TimeoutException;
import org.apache.syncope.core.provisioning.api.VirAttrHandler;
import org.apache.syncope.core.provisioning.api.propagation.PropagationActions;
import org.apache.syncope.core.provisioning.java.utils.MappingUtils;
import org.apache.syncope.core.spring.ImplementationManager;
import org.identityconnectors.framework.common.objects.AttributeBuilder;
import org.identityconnectors.framework.common.objects.ConnectorObject;
import org.identityconnectors.framework.common.objects.SearchResult;
import org.identityconnectors.framework.common.objects.filter.Filter;
import org.identityconnectors.framework.spi.SearchResultsHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional;

public class OutboundMatcher {

    protected static final Logger LOG = LoggerFactory.getLogger(OutboundMatcher.class);

    protected final MappingManager mappingManager;

    protected final UserDAO userDAO;

    protected final AnyUtilsFactory anyUtilsFactory;

    protected final VirSchemaDAO virSchemaDAO;

    protected final VirAttrHandler virAttrHandler;

    public OutboundMatcher(
            final MappingManager mappingManager,
            final UserDAO userDAO,
            final AnyUtilsFactory anyUtilsFactory,
            final VirSchemaDAO virSchemaDAO,
            final VirAttrHandler virAttrHandler) {

        this.mappingManager = mappingManager;
        this.userDAO = userDAO;
        this.anyUtilsFactory = anyUtilsFactory;
        this.virSchemaDAO = virSchemaDAO;
        this.virAttrHandler = virAttrHandler;
    }

    protected Optional<PushCorrelationRule> rule(final Provision provision) {
        Optional<? extends PushCorrelationRuleEntity> correlationRule = provision.getResource().getPushPolicy() == null
                ? Optional.empty()
                : provision.getResource().getPushPolicy().getCorrelationRule(provision.getAnyType());

        Optional<PushCorrelationRule> rule = Optional.empty();
        if (correlationRule.isPresent()) {
            try {
                rule = ImplementationManager.buildPushCorrelationRule(correlationRule.get().getImplementation());
            } catch (Exception e) {
                LOG.error("While building {}", correlationRule.get().getImplementation(), e);
            }
        }

        return rule;
    }

    public String getFIQL(final ConnectorObject connectorObject, final Provision provision) {
        return rule(provision).
                map(rule -> rule.getFIQL(connectorObject, provision)).
                orElseGet(() -> PushCorrelationRule.DEFAULT_FIQL_BUILDER.apply(connectorObject, provision));
    }

    public List<ConnectorObject> match(
            final PropagationTask task,
            final Connector connector,
            final Provision provision,
            final List<PropagationActions> actions,
            final String connObjectKeyValue) {

        Optional<PushCorrelationRule> rule = rule(provision);

        boolean isLinkedAccount = task.getAnyTypeKind() == AnyTypeKind.USER
                && userDAO.linkedAccountExists(task.getEntityKey(), connObjectKeyValue);
        Any<?> any = null;
        if (!isLinkedAccount) {
            any = anyUtilsFactory.getInstance(task.getAnyTypeKind()).dao().find(task.getEntityKey());
        }

        Set<String> moreAttrsToGet = new HashSet<>();
        actions.forEach(action -> moreAttrsToGet.addAll(action.moreAttrsToGet(Optional.of(task), provision)));

        List<ConnectorObject> result = new ArrayList<>();
        try {
            if (any != null && rule.isPresent()) {
                result.addAll(matchByCorrelationRule(
                        connector,
                        rule.get().getFilter(any, provision),
                        provision,
                        Optional.of(moreAttrsToGet.toArray(String[]::new)),
                        Optional.empty()));
            } else {
                MappingUtils.getConnObjectKeyItem(provision).flatMap(connObjectKeyItem -> matchByConnObjectKeyValue(
                        connector,
                        connObjectKeyItem,
                        connObjectKeyValue,
                        provision,
                        Optional.of(moreAttrsToGet.toArray(String[]::new)),
                        Optional.empty())).ifPresent(result::add);
            }
        } catch (RuntimeException e) {
            LOG.error("Could not match {} with any existing {}", any, provision.getObjectClass(), e);
        }

        if (any != null && result.size() == 1) {
            virAttrHandler.setValues(any, result.get(0));
        }

        return result;
    }

    @Transactional(readOnly = true)
    public List<ConnectorObject> match(
            final Connector connector,
            final Any<?> any,
            final Provision provision,
            final Optional<String[]> moreAttrsToGet,
            final LinkingMappingItem... linkingItems) {

        Set<String> matgFromPropagationActions = new HashSet<>();
        provision.getResource().getPropagationActions().forEach(impl -> {
            try {
                matgFromPropagationActions.addAll(
                        ImplementationManager.<PropagationActions>build(impl).
                                moreAttrsToGet(Optional.empty(), provision));
            } catch (Exception e) {
                LOG.error("While building {}", impl, e);
            }
        });
        Optional<String[]> effectiveMATG = Optional.of(Stream.concat(
                moreAttrsToGet.stream().flatMap(Stream::of),
                matgFromPropagationActions.stream()).toArray(String[]::new));

        Optional<PushCorrelationRule> rule = rule(provision);

        List<ConnectorObject> result = new ArrayList<>();
        try {
            if (rule.isPresent()) {
                result.addAll(matchByCorrelationRule(
                        connector,
                        rule.get().getFilter(any, provision),
                        provision,
                        effectiveMATG,
                        ArrayUtils.isEmpty(linkingItems)
                        ? Optional.empty() : Optional.of(List.of(linkingItems))));
            } else {
                Optional<? extends MappingItem> connObjectKeyItem = MappingUtils.getConnObjectKeyItem(provision);
                Optional<String> connObjectKeyValue = mappingManager.getConnObjectKeyValue(any, provision);

                if (connObjectKeyItem.isPresent() && connObjectKeyValue.isPresent()) {
                    matchByConnObjectKeyValue(
                            connector,
                            connObjectKeyItem.get(),
                            connObjectKeyValue.get(),
                            provision,
                            effectiveMATG,
                            ArrayUtils.isEmpty(linkingItems)
                            ? Optional.empty() : Optional.of(List.of(linkingItems))).
                            ifPresent(result::add);
                }
            }
        } catch (RuntimeException e) {
            LOG.error("Could not match {} with any existing {}", any, provision.getObjectClass(), e);
        }

        if (any != null && result.size() == 1) {
            virAttrHandler.setValues(any, result.get(0));
        }

        return result;
    }

    protected List<ConnectorObject> matchByCorrelationRule(
            final Connector connector,
            final Filter filter,
            final Provision provision,
            final Optional<String[]> moreAttrsToGet,
            final Optional<Collection<LinkingMappingItem>> linkingItems) {

        Stream<MappingItem> items = Stream.concat(
                provision.getMapping().getItems().stream(),
                linkingItems.isPresent()
                ? linkingItems.get().stream()
                : virSchemaDAO.findByProvision(provision).stream().map(VirSchema::asLinkingMappingItem));

        List<ConnectorObject> objs = new ArrayList<>();
        try {
            connector.search(provision.getObjectClass(), filter, new SearchResultsHandler() {

                @Override
                public void handleResult(final SearchResult result) {
                    // nothing to do
                }

                @Override
                public boolean handle(final ConnectorObject connectorObject) {
                    objs.add(connectorObject);
                    return true;
                }
            }, MappingUtils.buildOperationOptions(items, moreAttrsToGet.orElse(null)));
        } catch (TimeoutException toe) {
            LOG.debug("Request timeout", toe);
            throw toe;
        } catch (RuntimeException ignore) {
            LOG.debug("Unexpected exception", ignore);
        }

        return objs;
    }

    @Transactional(readOnly = true)
    public Optional<ConnectorObject> matchByConnObjectKeyValue(
            final Connector connector,
            final MappingItem connObjectKeyItem,
            final String connObjectKeyValue,
            final Provision provision,
            final Optional<String[]> moreAttrsToGet,
            final Optional<Collection<LinkingMappingItem>> linkingItems) {

        Stream<MappingItem> items = Stream.concat(
                provision.getMapping().getItems().stream(),
                linkingItems.isPresent()
                ? linkingItems.get().stream()
                : virSchemaDAO.findByProvision(provision).stream().map(VirSchema::asLinkingMappingItem));

        ConnectorObject obj = null;
        try {
            obj = connector.getObject(
                    provision.getObjectClass(),
                    AttributeBuilder.build(connObjectKeyItem.getExtAttrName(), connObjectKeyValue),
                    provision.isIgnoreCaseMatch(),
                    MappingUtils.buildOperationOptions(items, moreAttrsToGet.orElse(null)));
        } catch (TimeoutException toe) {
            LOG.debug("Request timeout", toe);
            throw toe;
        } catch (RuntimeException ignore) {
            LOG.debug("While resolving {}", connObjectKeyValue, ignore);
        }

        return Optional.ofNullable(obj);
    }
}
