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

import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.time.Duration;
import java.time.OffsetDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.syncope.client.console.SyncopeConsoleSession;
import org.apache.syncope.client.console.SyncopeWebApplication;
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.SearchUtils;
import org.apache.syncope.client.console.panels.search.UserSearchPanel;
import org.apache.syncope.client.console.rest.SchemaRestClient;
import org.apache.syncope.client.console.wicket.markup.html.form.MultiFieldPanel;
import org.apache.syncope.client.lib.SyncopeClient;
import org.apache.syncope.client.ui.commons.DateOps;
import org.apache.syncope.client.ui.commons.markup.html.form.AjaxCheckBoxPanel;
import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDateTimeFieldPanel;
import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
import org.apache.syncope.client.ui.commons.markup.html.form.AjaxGridFieldPanel;
import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPalettePanel;
import org.apache.syncope.client.ui.commons.markup.html.form.AjaxSpinnerFieldPanel;
import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
import org.apache.syncope.client.ui.commons.markup.html.form.FieldPanel;
import org.apache.syncope.common.lib.Schema;
import org.apache.syncope.common.lib.report.SearchCondition;
import org.apache.syncope.common.lib.search.AbstractFiqlSearchConditionBuilder;
import org.apache.syncope.common.lib.to.EntityTO;
import org.apache.syncope.common.lib.to.SchemaTO;
import org.apache.syncope.common.lib.types.SchemaType;
import org.apache.wicket.PageReference;
import org.apache.wicket.core.util.lang.PropertyResolver;
import org.apache.wicket.core.util.lang.PropertyResolverConverter;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
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.PropertyModel;
import org.apache.wicket.model.ResourceModel;
import org.apache.wicket.model.util.ListModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.PropertyAccessorFactory;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;

public class BeanPanel<T extends Serializable> extends Panel {

    private static final long serialVersionUID = 3905038169553185171L;

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

    private final List<String> excluded;

    private final Map<String, Pair<AbstractFiqlSearchConditionBuilder<?, ?, ?>, List<SearchClause>>> sCondWrapper;

    public BeanPanel(final String id, final IModel<T> bean, final PageReference pageRef, final String... excluded) {
        this(id, bean, null, pageRef, excluded);
    }

    public BeanPanel(
            final String id,
            final IModel<T> bean,
            final Map<String, Pair<AbstractFiqlSearchConditionBuilder<?, ?, ?>, List<SearchClause>>> sCondWrapper,
            final PageReference pageRef,
            final String... excluded) {

        super(id, bean);
        setOutputMarkupId(true);

        this.sCondWrapper = sCondWrapper;

        this.excluded = new ArrayList<>(List.of(excluded));
        this.excluded.add("serialVersionUID");
        this.excluded.add("class");

        LoadableDetachableModel<List<String>> model = new LoadableDetachableModel<>() {

            private static final long serialVersionUID = 5275935387613157437L;

            @Override
            protected List<String> load() {
                List<String> result = new ArrayList<>();

                if (BeanPanel.this.getDefaultModelObject() != null) {
                    ReflectionUtils.doWithFields(BeanPanel.this.getDefaultModelObject().getClass(),
                            field -> result.add(field.getName()),
                            field -> !field.isSynthetic() && !BeanPanel.this.excluded.contains(field.getName()));
                }

                return result;
            }
        };

        add(new ListView<>("propView", model) {

            private static final long serialVersionUID = 9101744072914090143L;

            @SuppressWarnings({ "unchecked", "rawtypes" })
            @Override
            protected void populateItem(final ListItem<String> item) {
                String fieldName = item.getModelObject();

                item.add(new Label("fieldName", new ResourceModel(fieldName, fieldName)));

                Field field = ReflectionUtils.findField(bean.getObject().getClass(), fieldName);
                if (field == null) {
                    return;
                }

                SearchCondition scondAnnot = field.getAnnotation(SearchCondition.class);
                Schema schemaAnnot = field.getAnnotation(Schema.class);

                BeanWrapper wrapper = PropertyAccessorFactory.forBeanPropertyAccess(bean.getObject());

                Panel panel;

                if (scondAnnot != null) {
                    String fiql = (String) wrapper.getPropertyValue(fieldName);

                    List<SearchClause> clauses = SearchUtils.getSearchClauses(fiql);

                    AbstractFiqlSearchConditionBuilder<?, ?, ?> builder;
                    switch (scondAnnot.type()) {
                        case "USER":
                            panel = new UserSearchPanel.Builder(
                                    new ListModel<>(clauses), pageRef).required(false).build("value");
                            builder = SyncopeClient.getUserSearchConditionBuilder();
                            break;

                        case "GROUP":
                            panel = new GroupSearchPanel.Builder(
                                    new ListModel<>(clauses), pageRef).required(false).build("value");
                            builder = SyncopeClient.getGroupSearchConditionBuilder();
                            break;

                        default:
                            panel = new AnyObjectSearchPanel.Builder(
                                    scondAnnot.type(),
                                    new ListModel<>(clauses), pageRef).required(false).build("value");
                            builder = SyncopeClient.getAnyObjectSearchConditionBuilder(scondAnnot.type());
                    }

                    if (BeanPanel.this.sCondWrapper != null) {
                        BeanPanel.this.sCondWrapper.put(fieldName, Pair.of(builder, clauses));
                    }
                } else if (List.class.equals(field.getType())) {
                    Class<?> listItemType = field.getGenericType() instanceof ParameterizedType
                            ? (Class<?>) ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0]
                            : String.class;

                    if (listItemType.equals(String.class) && schemaAnnot != null) {
                        List<SchemaTO> choices = new ArrayList<>();

                        for (SchemaType type : schemaAnnot.type()) {
                            switch (type) {
                                case PLAIN:
                                    choices.addAll(
                                            SchemaRestClient.getSchemas(SchemaType.PLAIN, schemaAnnot.anyTypeKind()));
                                    break;

                                case DERIVED:
                                    choices.addAll(
                                            SchemaRestClient.getSchemas(SchemaType.DERIVED, schemaAnnot.anyTypeKind()));
                                    break;

                                case VIRTUAL:
                                    choices.addAll(
                                            SchemaRestClient.getSchemas(SchemaType.VIRTUAL, schemaAnnot.anyTypeKind()));
                                    break;

                                default:
                            }
                        }

                        panel = new AjaxPalettePanel.Builder<>().setName(fieldName).build(
                                "value",
                                new PropertyModel<>(bean.getObject(), fieldName),
                                new ListModel<>(choices.stream().map(EntityTO::getKey).collect(Collectors.toList()))).
                                hideLabel();
                    } else if (listItemType.isEnum()) {
                        panel = new AjaxPalettePanel.Builder<>().setName(fieldName).build(
                                "value",
                                new PropertyModel<>(bean.getObject(), fieldName),
                                new ListModel(List.of(listItemType.getEnumConstants()))).hideLabel();
                    } else {
                        panel = new MultiFieldPanel.Builder<>(
                                new PropertyModel<>(bean.getObject(), fieldName)).build(
                                "value",
                                fieldName,
                                buildSinglePanel(bean.getObject(), listItemType, fieldName, "panel")).hideLabel();
                    }
                } else if (Map.class.equals(field.getType())) {
                    panel = new AjaxGridFieldPanel(
                            "value", fieldName, new PropertyModel<>(bean, fieldName)).hideLabel();
                } else {
                    panel = buildSinglePanel(bean.getObject(), field.getType(), fieldName, "value").hideLabel();
                }

                item.add(panel.setRenderBodyOnly(true));
            }
        }.setReuseItems(true).setOutputMarkupId(true));
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    private static FieldPanel buildSinglePanel(
            final Serializable bean, final Class<?> type, final String fieldName, final String id) {

        PropertyModel model = new PropertyModel<>(bean, fieldName);

        FieldPanel result;
        if (ClassUtils.isAssignable(Boolean.class, type)) {
            result = new AjaxCheckBoxPanel(id, fieldName, model);
        } else if (ClassUtils.isAssignable(Number.class, type)) {
            result = new AjaxSpinnerFieldPanel.Builder<>().build(
                    id, fieldName, (Class<Number>) ClassUtils.resolvePrimitiveIfNecessary(type), model);
        } else if (Date.class.equals(type)) {
            result = new AjaxDateTimeFieldPanel(id, fieldName, model,
                    DateFormatUtils.ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT);
        } else if (OffsetDateTime.class.equals(type)) {
            result = new AjaxDateTimeFieldPanel(id, fieldName, new DateOps.WrappedDateModel(model),
                    DateFormatUtils.ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT);
        } else if (type.isEnum()) {
            result = new AjaxDropDownChoicePanel(id, fieldName, model).setChoices(List.of(type.getEnumConstants()));
        } else if (Duration.class.equals(type)) {
            result = new AjaxTextFieldPanel(id, fieldName, new IModel<>() {

                private static final long serialVersionUID = 807008909842554829L;

                @Override
                public String getObject() {
                    return Optional.ofNullable(PropertyResolver.getValue(fieldName, bean)).
                            map(Object::toString).orElse(null);
                }

                @Override
                public void setObject(final String object) {
                    PropertyResolverConverter prc = new PropertyResolverConverter(
                            SyncopeWebApplication.get().getConverterLocator(),
                            SyncopeConsoleSession.get().getLocale());
                    PropertyResolver.setValue(fieldName, bean, Duration.parse(object), prc);
                }
            });
        } else {
            // treat as String if nothing matched above
            result = new AjaxTextFieldPanel(id, fieldName, model);
        }

        result.hideLabel();
        return result;
    }
}
