/*
 * 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.job.report;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.commons.lang3.StringUtils;
import org.apache.syncope.common.lib.Attr;
import org.apache.syncope.common.lib.EntityTOUtils;
import org.apache.syncope.common.lib.SyncopeConstants;
import org.apache.syncope.common.lib.report.ReportletConf;
import org.apache.syncope.common.lib.report.UserReportletConf;
import org.apache.syncope.common.lib.report.UserReportletConf.Feature;
import org.apache.syncope.common.lib.to.AnyTO;
import org.apache.syncope.common.lib.to.MembershipTO;
import org.apache.syncope.common.lib.to.RelationshipTO;
import org.apache.syncope.common.lib.to.UserTO;
import org.apache.syncope.common.lib.types.AnyTypeKind;
import org.apache.syncope.core.persistence.api.dao.AnyDAO;
import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
import org.apache.syncope.core.persistence.api.dao.RealmDAO;
import org.apache.syncope.core.persistence.api.dao.ReportletConfClass;
import org.apache.syncope.core.persistence.api.dao.UserDAO;
import org.apache.syncope.core.persistence.api.entity.user.UMembership;
import org.apache.syncope.core.persistence.api.entity.user.URelationship;
import org.apache.syncope.core.persistence.api.entity.user.User;
import org.apache.syncope.core.persistence.api.search.SearchCondConverter;
import org.apache.syncope.core.persistence.api.search.SearchCondVisitor;
import org.apache.syncope.core.provisioning.api.data.AnyObjectDataBinder;
import org.apache.syncope.core.provisioning.api.data.GroupDataBinder;
import org.apache.syncope.core.provisioning.api.data.UserDataBinder;
import org.apache.syncope.core.provisioning.api.utils.FormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;

@ReportletConfClass(UserReportletConf.class)
public class UserReportlet extends AbstractReportlet {

    @Autowired
    protected RealmDAO realmDAO;

    @Autowired
    protected UserDAO userDAO;

    @Autowired
    protected AnySearchDAO searchDAO;

    @Autowired
    protected UserDataBinder userDataBinder;

    @Autowired
    protected GroupDataBinder groupDataBinder;

    @Autowired
    protected AnyObjectDataBinder anyObjectDataBinder;

    @Autowired
    protected SearchCondVisitor searchCondVisitor;

    protected UserReportletConf conf;

    protected void doExtractResources(final ContentHandler handler, final AnyTO anyTO)
            throws SAXException {

        if (anyTO.getResources().isEmpty()) {
            LOG.debug("No resources found for {}[{}]", anyTO.getClass().getSimpleName(), anyTO.getKey());
        } else {
            AttributesImpl atts = new AttributesImpl();
            handler.startElement("", "", "resources", null);

            for (String resourceName : anyTO.getResources()) {
                atts.clear();

                atts.addAttribute("", "", ReportXMLConst.ATTR_NAME, ReportXMLConst.XSD_STRING, resourceName);
                handler.startElement("", "", "resource", atts);
                handler.endElement("", "", "resource");
            }

            handler.endElement("", "", "resources");
        }
    }

    protected void doExtractAttributes(
            final ContentHandler handler,
            final AnyTO anyTO,
            final Collection<String> attrs,
            final Collection<String> derAttrs,
            final Collection<String> virAttrs) throws SAXException {

        AttributesImpl atts = new AttributesImpl();
        if (!attrs.isEmpty()) {
            Map<String, Attr> attrMap = EntityTOUtils.buildAttrMap(anyTO.getPlainAttrs());

            handler.startElement("", "", "attributes", null);
            for (String attrName : attrs) {
                atts.clear();

                atts.addAttribute("", "", ReportXMLConst.ATTR_NAME, ReportXMLConst.XSD_STRING, attrName);
                handler.startElement("", "", "attribute", atts);

                if (attrMap.containsKey(attrName)) {
                    for (String value : attrMap.get(attrName).getValues()) {
                        handler.startElement("", "", "value", null);
                        handler.characters(value.toCharArray(), 0, value.length());
                        handler.endElement("", "", "value");
                    }
                } else {
                    LOG.debug("{} not found for {}[{}]", attrName,
                            anyTO.getClass().getSimpleName(), anyTO.getKey());
                }

                handler.endElement("", "", "attribute");
            }
            handler.endElement("", "", "attributes");
        }

        if (!derAttrs.isEmpty()) {
            Map<String, Attr> derAttrMap = EntityTOUtils.buildAttrMap(anyTO.getDerAttrs());

            handler.startElement("", "", "derivedAttributes", null);
            for (String attrName : derAttrs) {
                atts.clear();

                atts.addAttribute("", "", ReportXMLConst.ATTR_NAME, ReportXMLConst.XSD_STRING, attrName);
                handler.startElement("", "", "derivedAttribute", atts);

                if (derAttrMap.containsKey(attrName)) {
                    for (String value : derAttrMap.get(attrName).getValues()) {
                        handler.startElement("", "", "value", null);
                        handler.characters(value.toCharArray(), 0, value.length());
                        handler.endElement("", "", "value");
                    }
                } else {
                    LOG.debug("{} not found for {}[{}]", attrName,
                            anyTO.getClass().getSimpleName(), anyTO.getKey());
                }

                handler.endElement("", "", "derivedAttribute");
            }
            handler.endElement("", "", "derivedAttributes");
        }

        if (!virAttrs.isEmpty()) {
            Map<String, Attr> virAttrMap = EntityTOUtils.buildAttrMap(anyTO.getVirAttrs());

            handler.startElement("", "", "virtualAttributes", null);
            for (String attrName : virAttrs) {
                atts.clear();

                atts.addAttribute("", "", ReportXMLConst.ATTR_NAME, ReportXMLConst.XSD_STRING, attrName);
                handler.startElement("", "", "virtualAttribute", atts);

                if (virAttrMap.containsKey(attrName)) {
                    for (String value : virAttrMap.get(attrName).getValues()) {
                        handler.startElement("", "", "value", null);
                        handler.characters(value.toCharArray(), 0, value.length());
                        handler.endElement("", "", "value");
                    }
                } else {
                    LOG.debug("{} not found for {}[{}]", attrName,
                            anyTO.getClass().getSimpleName(), anyTO.getKey());
                }

                handler.endElement("", "", "virtualAttribute");
            }
            handler.endElement("", "", "virtualAttributes");
        }
    }

    protected void doExtract(final ContentHandler handler, final List<User> users) throws SAXException {
        AttributesImpl atts = new AttributesImpl();
        for (User user : users) {
            atts.clear();

            for (Feature feature : conf.getFeatures()) {
                String type = null;
                String value = null;
                switch (feature) {
                    case key:
                        type = ReportXMLConst.XSD_STRING;
                        value = user.getKey();
                        break;

                    case username:
                        type = ReportXMLConst.XSD_STRING;
                        value = user.getUsername();
                        break;

                    case status:
                        type = ReportXMLConst.XSD_STRING;
                        value = user.getStatus();
                        break;

                    case creationDate:
                        type = ReportXMLConst.XSD_DATETIME;
                        value = user.getCreationDate() == null
                                ? ""
                                : FormatUtils.format(user.getCreationDate());
                        break;

                    case lastLoginDate:
                        type = ReportXMLConst.XSD_DATETIME;
                        value = user.getLastLoginDate() == null
                                ? ""
                                : FormatUtils.format(user.getLastLoginDate());
                        break;

                    case changePwdDate:
                        type = ReportXMLConst.XSD_DATETIME;
                        value = user.getChangePwdDate() == null
                                ? ""
                                : FormatUtils.format(user.getChangePwdDate());
                        break;

                    case passwordHistorySize:
                        type = ReportXMLConst.XSD_INT;
                        value = String.valueOf(user.getPasswordHistory().size());
                        break;

                    case failedLoginCount:
                        type = ReportXMLConst.XSD_INT;
                        value = String.valueOf(user.getFailedLogins());
                        break;

                    default:
                }

                if (type != null && value != null) {
                    atts.addAttribute("", "", feature.name(), type, value);
                }
            }

            handler.startElement("", "", "user", atts);

            // Using UserTO for attribute values, since the conversion logic of
            // values to String is already encapsulated there
            UserTO userTO = userDataBinder.getUserTO(user, true);

            doExtractAttributes(handler, userTO, conf.getPlainAttrs(), conf.getDerAttrs(), conf.getVirAttrs());

            if (conf.getFeatures().contains(Feature.relationships)) {
                handler.startElement("", "", "relationships", null);

                for (RelationshipTO rel : userTO.getRelationships()) {
                    atts.clear();

                    atts.addAttribute("", "", "anyObjectKey",
                            ReportXMLConst.XSD_STRING, rel.getOtherEndKey());
                    handler.startElement("", "", "relationship", atts);

                    if (conf.getFeatures().contains(Feature.resources)) {
                        for (URelationship actualRel : user.getRelationships(rel.getOtherEndKey())) {
                            doExtractResources(
                                    handler, anyObjectDataBinder.getAnyObjectTO(actualRel.getRightEnd(), true));
                        }
                    }

                    handler.endElement("", "", "relationship");
                }

                handler.endElement("", "", "relationships");
            }
            if (conf.getFeatures().contains(Feature.memberships)) {
                handler.startElement("", "", "memberships", null);

                for (MembershipTO memb : userTO.getMemberships()) {
                    atts.clear();

                    atts.addAttribute("", "", "groupKey",
                            ReportXMLConst.XSD_STRING, memb.getGroupKey());
                    atts.addAttribute("", "", "groupName", ReportXMLConst.XSD_STRING, memb.getGroupName());
                    handler.startElement("", "", "membership", atts);

                    if (conf.getFeatures().contains(Feature.resources)) {
                        UMembership actualMemb = user.getMembership(memb.getGroupKey()).orElse(null);
                        if (actualMemb == null) {
                            LOG.warn("Unexpected: cannot find membership for group {} for user {}",
                                    memb.getGroupKey(), user);
                        } else {
                            doExtractResources(handler, groupDataBinder.getGroupTO(actualMemb.getRightEnd(), true));
                        }
                    }

                    handler.endElement("", "", "membership");
                }

                handler.endElement("", "", "memberships");
            }

            if (conf.getFeatures().contains(Feature.resources)) {
                doExtractResources(handler, userTO);
            }

            handler.endElement("", "", "user");
        }
    }

    protected void doExtractConf(final ContentHandler handler) throws SAXException {
        AttributesImpl atts = new AttributesImpl();
        handler.startElement("", "", "configurations", null);
        handler.startElement("", "", "userAttributes", atts);

        for (Feature feature : conf.getFeatures()) {
            atts.clear();
            handler.startElement("", "", "feature", atts);
            handler.characters(feature.name().toCharArray(), 0, feature.name().length());
            handler.endElement("", "", "feature");
        }

        for (String attr : conf.getPlainAttrs()) {
            atts.clear();
            handler.startElement("", "", "attribute", atts);
            handler.characters(attr.toCharArray(), 0, attr.length());
            handler.endElement("", "", "attribute");
        }

        for (String derAttr : conf.getDerAttrs()) {
            atts.clear();
            handler.startElement("", "", "derAttribute", atts);
            handler.characters(derAttr.toCharArray(), 0, derAttr.length());
            handler.endElement("", "", "derAttribute");
        }

        for (String virAttr : conf.getVirAttrs()) {
            atts.clear();
            handler.startElement("", "", "virAttribute", atts);
            handler.characters(virAttr.toCharArray(), 0, virAttr.length());
            handler.endElement("", "", "virAttribute");
        }

        handler.endElement("", "", "userAttributes");
        handler.endElement("", "", "configurations");
    }

    protected int count() {
        return StringUtils.isBlank(conf.getMatchingCond())
                ? userDAO.count()
                : searchDAO.count(
                        realmDAO.getRoot(),
                        true,
                        SyncopeConstants.FULL_ADMIN_REALMS,
                        SearchCondConverter.convert(searchCondVisitor, conf.getMatchingCond()),
                        AnyTypeKind.USER);
    }

    @Override
    protected void doExtract(
            final ReportletConf conf,
            final ContentHandler handler,
            final AtomicReference<String> status)
            throws SAXException {

        if (conf instanceof UserReportletConf) {
            this.conf = UserReportletConf.class.cast(conf);
        } else {
            throw new ReportException(new IllegalArgumentException("Invalid configuration provided"));
        }

        doExtractConf(handler);

        int total = count();
        int pages = (total / AnyDAO.DEFAULT_PAGE_SIZE) + 1;

        status.set("Processing " + total + " users in " + pages + " pages");

        for (int page = 1; page <= pages; page++) {
            status.set("Processing " + total + " users: page " + page + " of " + pages);

            List<User> users;
            if (StringUtils.isBlank(this.conf.getMatchingCond())) {
                users = userDAO.findAll(page, AnyDAO.DEFAULT_PAGE_SIZE);
            } else {
                users = searchDAO.search(
                        realmDAO.getRoot(),
                        true,
                        SyncopeConstants.FULL_ADMIN_REALMS,
                        SearchCondConverter.convert(searchCondVisitor, this.conf.getMatchingCond()),
                        page,
                        AnyDAO.DEFAULT_PAGE_SIZE,
                        List.of(),
                        AnyTypeKind.USER);
            }

            doExtract(handler, users);
        }
    }
}
