/*******************************************************************************
 * Copyright (C) 2022, 1C-Soft LLC and others.
 *
 * This program and the accompanying materials are made
 * available under the terms of the Eclipse Public License 2.0
 * which is available at https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     1C-Soft LLC - initial API and implementation
 *******************************************************************************/

package com.e1c.v8codestyle.form.check;

import java.util.HashSet;
import java.util.Set;

import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EStructuralFeature;

import com._1c.g5.v8.bm.core.IBmObject;
import com._1c.g5.v8.bm.core.event.BmChangeEvent;
import com._1c.g5.v8.bm.core.event.BmSubEvent;
import com._1c.g5.v8.dt.form.model.Form;
import com._1c.g5.v8.dt.form.model.FormPackage;
import com.e1c.g5.v8.dt.check.ICheckDefinition;
import com.e1c.g5.v8.dt.check.components.IBasicCheckExtension;
import com.e1c.g5.v8.dt.check.context.CheckContextCollectingSession;
import com.e1c.g5.v8.dt.check.context.OnModelFeatureChangeContextCollector;

/**
 * The extension that registers {@link Form} for model check if a command handler
 * or an item contained in the form has been changed
 *
 * @author Artem Iliukhin
 */
public class CommandHandlerChangeExtension
    implements IBasicCheckExtension
{
    @Override
    public void configureContextCollector(final ICheckDefinition definition)
    {
        OnModelFeatureChangeContextCollector collector = (IBmObject bmObject, EStructuralFeature feature,
            BmSubEvent bmEvent, CheckContextCollectingSession contextSession) -> {
            if (isActionChanged(feature) || isCommandChanged(feature, bmEvent))
            {
                IBmObject top = bmObject.bmIsTop() ? bmObject : bmObject.bmGetTopObject();
                if (top instanceof Form)
                {
                    contextSession.addModelCheck(top);
                }
            }
        };

        Set<EClass> containdedObjects = new HashSet<>();
        containdedObjects.add(FormPackage.Literals.FORM_COMMAND);
        definition.addCheckedModelObjects(FormPackage.Literals.FORM, true, containdedObjects);
        definition.addModelFeatureChangeContextCollector(collector, FormPackage.Literals.FORM_COMMAND);
    }

    private boolean isActionChanged(EStructuralFeature feature)
    {
        return feature == FormPackage.Literals.FORM_COMMAND__ACTION;
    }

    private boolean isCommandChanged(EStructuralFeature feature, BmSubEvent bmEvent)
    {
        if (feature == FormPackage.Literals.FORM__FORM_COMMANDS)
        {
            for (Notification notification : ((BmChangeEvent)bmEvent).getNotifications(feature))
            {
                if (notification.getEventType() == Notification.ADD
                    || notification.getEventType() == Notification.REMOVE)
                {
                    return true;
                }
            }
        }
        return false;
    }
}
