/*
 * 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.client.console.notifications;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.syncope.client.console.SyncopeConsoleSession;
import org.apache.syncope.client.console.events.EventCategoryPanel;
import org.apache.syncope.client.console.panels.search.AbstractSearchPanel;
import org.apache.syncope.client.console.panels.search.AnyObjectSearchPanel;
import org.apache.syncope.client.console.panels.search.GroupSearchPanel;
import org.apache.syncope.client.console.panels.search.SearchClause;
import org.apache.syncope.client.console.panels.search.UserSearchPanel;
import org.apache.syncope.client.console.rest.AnyTypeRestClient;
import org.apache.syncope.client.console.rest.AuditRestClient;
import org.apache.syncope.client.console.rest.ImplementationRestClient;
import org.apache.syncope.client.console.rest.NotificationRestClient;
import org.apache.syncope.client.console.rest.SchemaRestClient;
import org.apache.syncope.client.console.wicket.markup.html.form.MultiFieldPanel;
import org.apache.syncope.client.console.wicket.markup.html.form.MultiPanel;
import org.apache.syncope.client.console.wizards.BaseAjaxWizardBuilder;
import org.apache.syncope.client.ui.commons.Constants;
import org.apache.syncope.client.ui.commons.markup.html.form.AjaxCheckBoxPanel;
import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
import org.apache.syncope.common.lib.SyncopeClientException;
import org.apache.syncope.common.lib.to.AnyTypeTO;
import org.apache.syncope.common.lib.to.DerSchemaTO;
import org.apache.syncope.common.lib.to.EntityTO;
import org.apache.syncope.common.lib.to.NotificationTO;
import org.apache.syncope.common.lib.to.PlainSchemaTO;
import org.apache.syncope.common.lib.to.VirSchemaTO;
import org.apache.syncope.common.lib.types.AnyTypeKind;
import org.apache.syncope.common.lib.types.IdRepoImplementationType;
import org.apache.syncope.common.lib.types.SchemaType;
import org.apache.syncope.common.lib.types.TraceLevel;
import org.apache.wicket.PageReference;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
import org.apache.wicket.extensions.wizard.WizardModel;
import org.apache.wicket.extensions.wizard.WizardStep;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.LoadableDetachableModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.PropertyModel;
import org.apache.wicket.model.ResourceModel;
import org.apache.wicket.model.util.ListModel;
import org.apache.wicket.validation.validator.EmailAddressValidator;

public class NotificationWizardBuilder extends BaseAjaxWizardBuilder<NotificationWrapper> {

    private static final long serialVersionUID = -1975312550059578553L;

    private final NotificationRestClient restClient = new NotificationRestClient();

    /**
     * Construct.
     *
     * @param notificationTO notification.
     * @param pageRef Caller page reference.
     */
    public NotificationWizardBuilder(final NotificationTO notificationTO, final PageReference pageRef) {
        super(new NotificationWrapper(notificationTO), pageRef);
    }

    @Override
    protected Serializable onApplyInternal(final NotificationWrapper modelObject) {
        modelObject.fillRecipientConditions();
        modelObject.fillAboutConditions();

        final boolean createFlag = modelObject.getInnerObject().getKey() == null;
        if (createFlag) {
            NotificationRestClient.create(modelObject.getInnerObject());
        } else {
            NotificationRestClient.update(modelObject.getInnerObject());
        }

        return null;
    }

    @Override
    protected WizardModel buildModelSteps(final NotificationWrapper modelObject, final WizardModel wizardModel) {
        wizardModel.add(new Details(modelObject));
        wizardModel.add(new Recipients(modelObject));
        wizardModel.add(new Events(modelObject));
        wizardModel.add(new Abouts(modelObject));
        return wizardModel;
    }

    public class Details extends WizardStep {

        private static final long serialVersionUID = -7709805590497687958L;

        public Details(final NotificationWrapper modelObject) {
            NotificationTO notificationTO = modelObject.getInnerObject();
            boolean createFlag = notificationTO.getKey() == null;

            AjaxTextFieldPanel sender = new AjaxTextFieldPanel("sender", getString("sender"),
                    new PropertyModel<>(notificationTO, "sender"));
            sender.addRequiredLabel();
            sender.addValidator(EmailAddressValidator.getInstance());
            add(sender);

            AjaxTextFieldPanel subject = new AjaxTextFieldPanel("subject", getString("subject"),
                    new PropertyModel<>(notificationTO, "subject"));
            subject.addRequiredLabel();
            add(subject);

            AjaxDropDownChoicePanel<String> template = new AjaxDropDownChoicePanel<>(
                    "template", getString("template"),
                    new PropertyModel<>(notificationTO, "template"));
            template.setChoices(restClient.listTemplates().stream().
                    map(EntityTO::getKey).collect(Collectors.toList()));

            template.addRequiredLabel();
            add(template);

            AjaxDropDownChoicePanel<TraceLevel> traceLevel = new AjaxDropDownChoicePanel<>(
                    "traceLevel", getString("traceLevel"),
                    new PropertyModel<>(notificationTO, "traceLevel"));
            traceLevel.setChoices(List.of(TraceLevel.values()));
            traceLevel.addRequiredLabel();
            add(traceLevel);

            final AjaxCheckBoxPanel isActive = new AjaxCheckBoxPanel("isActive",
                    getString("isActive"), new PropertyModel<>(notificationTO, "active"));
            if (createFlag) {
                isActive.getField().setDefaultModelObject(Boolean.TRUE);
            }
            add(isActive);
        }

    }

    public static class Events extends WizardStep {

        private static final long serialVersionUID = -7709805590497687958L;

        public Events(final NotificationWrapper modelObject) {
            setTitleModel(new ResourceModel("events"));

            add(new EventCategoryPanel(
                    "eventSelection",
                    AuditRestClient.listEvents(),
                    new PropertyModel<>(modelObject.getInnerObject(), "events")) {

                private static final long serialVersionUID = 6429053774964787735L;

                @Override
                protected List<String> getListAuthRoles() {
                    return List.of();
                }

                @Override
                protected List<String> getChangeAuthRoles() {
                    return List.of();
                }
            });
        }
    }

    public static class About extends Panel {

        private static final long serialVersionUID = -9149543787708482882L;

        public About(final String id, final IModel<Pair<String, List<SearchClause>>> model) {
            super(id, model);
            setOutputMarkupId(true);

            AjaxDropDownChoicePanel<String> type =
                    new AjaxDropDownChoicePanel<>("about", "anyType", new Model<>() {

                        private static final long serialVersionUID = -2350296434572623272L;

                        @Override
                        public String getObject() {
                            return model.getObject().getLeft();
                        }

                        @Override
                        public void setObject(final String object) {
                            model.setObject(Pair.of(object, model.getObject().getRight()));
                        }

                    });
            type.setChoices(AnyTypeRestClient.list());
            type.addRequiredLabel();
            add(type);

            ListModel<SearchClause> clauseModel = new ListModel<>() {

                private static final long serialVersionUID = 3769540249683319782L;

                @Override
                public List<SearchClause> getObject() {
                    return model.getObject().getRight();
                }

                @Override
                public void setObject(final List<SearchClause> object) {
                    model.getObject().setValue(object);
                }
            };

            WebMarkupContainer searchContainer = new WebMarkupContainer("search");
            add(searchContainer.setOutputMarkupId(true));

            searchContainer.add(getClauseBuilder(model.getObject().getLeft(), clauseModel).build("clauses"));

            type.getField().add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {

                private static final long serialVersionUID = -1107858522700306810L;

                @Override
                protected void onUpdate(final AjaxRequestTarget target) {
                    clauseModel.getObject().clear();
                    searchContainer.addOrReplace(getClauseBuilder(type.getModelObject(), clauseModel).
                            build("clauses").setRenderBodyOnly(true));
                    target.add(searchContainer);
                }
            });
        }

        private AbstractSearchPanel.Builder<?> getClauseBuilder(
                final String type, final ListModel<SearchClause> clauseModel) {

            AbstractSearchPanel.Builder<?> clause;

            switch (type) {
                case "USER":
                    clause = new UserSearchPanel.Builder(clauseModel);
                    break;

                case "GROUP":
                    clause = new GroupSearchPanel.Builder(clauseModel);
                    break;

                default:
                    clause = new AnyObjectSearchPanel.Builder(type, clauseModel);
            }

            return clause;
        }
    }

    public class Abouts extends WizardStep {

        private static final long serialVersionUID = -7709805590497687958L;

        public Abouts(final NotificationWrapper modelObject) {
            setTitleModel(new ResourceModel("about"));

            WebMarkupContainer aboutContainer = new WebMarkupContainer("about");
            aboutContainer.setOutputMarkupId(true);
            add(aboutContainer);

            IModel<List<Pair<String, List<SearchClause>>>> model = new PropertyModel<>(modelObject, "aboutClauses");

            aboutContainer.add(new MultiPanel<>("abouts", "abouts", model) {

                private static final long serialVersionUID = -2481579077338205547L;

                @Override
                protected Pair<String, List<SearchClause>> newModelObject() {
                    return Pair.<String, List<SearchClause>>of(AnyTypeKind.USER.name(), new ArrayList<>());
                }

                @Override
                protected About getItemPanel(final ListItem<Pair<String, List<SearchClause>>> item) {

                    return new About("panel", new Model<>() {

                        private static final long serialVersionUID = 6799404673615637845L;

                        @Override
                        public Pair<String, List<SearchClause>> getObject() {
                            return item.getModelObject();
                        }

                        @Override
                        public void setObject(final Pair<String, List<SearchClause>> object) {
                            item.setModelObject(object);
                        }

                        @Override
                        public void detach() {
                            // no detach
                        }
                    });
                }

                @Override
                protected void sendError(final String message) {
                    SyncopeConsoleSession.get().error(getString(Constants.OPERATION_ERROR));
                }
            }.hideLabel());
        }
    }

    public static class Recipients extends WizardStep {

        private static final long serialVersionUID = -7709805590497687958L;

        private final IModel<List<String>> recipientProviders = new LoadableDetachableModel<>() {

            private static final long serialVersionUID = 5275935387613157447L;

            @Override
            protected List<String> load() {
                return ImplementationRestClient.list(IdRepoImplementationType.RECIPIENTS_PROVIDER).stream().
                        map(EntityTO::getKey).sorted().collect(Collectors.toList());
            }
        };

        public Recipients(final NotificationWrapper modelObject) {
            setTitleModel(new ResourceModel("recipients"));

            NotificationTO notificationTO = modelObject.getInnerObject();

            AjaxTextFieldPanel recipientAttrName = new AjaxTextFieldPanel(
                    "recipientAttrName", new ResourceModel("recipientAttrName", "recipientAttrName").getObject(),
                    new PropertyModel<>(notificationTO, "recipientAttrName"));
            recipientAttrName.setChoices(getSchemas());
            recipientAttrName.addRequiredLabel();
            recipientAttrName.setTitle(getString("intAttrNameInfo.help")
                    + "<code>groups[groupName].attribute</code>, "
                    + "<code>users[userName].attribute</code>, "
                    + "<code>anyObjects[anyObjectName].attribute</code>, "
                    + "<code>relationships[relationshipType][anyType].attribute</code> or "
                    + "<code>memberships[groupName].attribute</code> or "
                    + "<code>privileges[applicationKey]</code>", true);
            add(recipientAttrName);

            AjaxTextFieldPanel staticRecipientsFieldPanel =
                    new AjaxTextFieldPanel("panel", "staticRecipients", new Model<>());
            staticRecipientsFieldPanel.addValidator(EmailAddressValidator.getInstance());
            add(new MultiFieldPanel.Builder<>(
                    new PropertyModel<List<String>>(notificationTO, "staticRecipients")).
                    build("staticRecipients", "staticRecipients", staticRecipientsFieldPanel).hideLabel());

            add(new UserSearchPanel.Builder(
                    new PropertyModel<>(modelObject, "recipientClauses")).
                    required(false).build("recipients"));

            AjaxDropDownChoicePanel<String> recipientsProvider = new AjaxDropDownChoicePanel<>(
                    "recipientsProvider", "recipientsProvider",
                    new PropertyModel<>(notificationTO, "recipientsProvider"), false);
            recipientsProvider.setChoices(recipientProviders.getObject());
            add(recipientsProvider);

            AjaxCheckBoxPanel selfAsRecipient = new AjaxCheckBoxPanel("selfAsRecipient",
                    getString("selfAsRecipient"), new PropertyModel<>(notificationTO, "selfAsRecipient"));
            if (notificationTO.getKey() == null) {
                selfAsRecipient.getField().setDefaultModelObject(Boolean.FALSE);
            }
            add(selfAsRecipient);
        }
    }

    private static List<String> getSchemas() {
        AnyTypeTO type = null;
        try {
            type = AnyTypeRestClient.read(AnyTypeKind.USER.name());
        } catch (SyncopeClientException e) {
            LOG.error("While reading all any types", e);
        }

        String[] anyTypeClasses = Optional.ofNullable(type).
                map(anyTypeTO -> anyTypeTO.getClasses().toArray(String[]::new)).orElseGet(() -> new String[0]);

        List<String> result = new ArrayList<>();
        result.add(Constants.USERNAME_FIELD_NAME);

        result.addAll(SchemaRestClient.<PlainSchemaTO>getSchemas(SchemaType.PLAIN, null, anyTypeClasses).
                stream().map(EntityTO::getKey).collect(Collectors.toList()));
        result.addAll(SchemaRestClient.<DerSchemaTO>getSchemas(SchemaType.DERIVED, null, anyTypeClasses).
                stream().map(EntityTO::getKey).collect(Collectors.toList()));
        result.addAll(SchemaRestClient.<VirSchemaTO>getSchemas(SchemaType.VIRTUAL, null, anyTypeClasses).
                stream().map(EntityTO::getKey).collect(Collectors.toList()));

        Collections.sort(result);
        return result;
    }
}
