/*******************************************************************************
 * Copyright (C) 2021, 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.autosort;

import static com._1c.g5.v8.dt.metadata.mdclass.MdClassPackage.Literals.CATALOG__ATTRIBUTES;
import static com._1c.g5.v8.dt.metadata.mdclass.MdClassPackage.Literals.CATALOG__COMMANDS;
import static com._1c.g5.v8.dt.metadata.mdclass.MdClassPackage.Literals.CATALOG__FORMS;
import static com._1c.g5.v8.dt.metadata.mdclass.MdClassPackage.Literals.CATALOG__TABULAR_SECTIONS;
import static com._1c.g5.v8.dt.metadata.mdclass.MdClassPackage.Literals.CATALOG__TEMPLATES;
import static com._1c.g5.v8.dt.metadata.mdclass.MdClassPackage.Literals.HTTP_SERVICE__URL_TEMPLATES;
import static com._1c.g5.v8.dt.metadata.mdclass.MdClassPackage.Literals.INFORMATION_REGISTER__RESOURCES;
import static com._1c.g5.v8.dt.metadata.mdclass.MdClassPackage.Literals.URL_TEMPLATE__METHODS;
import static com._1c.g5.v8.dt.metadata.mdclass.MdClassPackage.Literals.WEB_SERVICE__OPERATIONS;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ProjectScope;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.preferences.ConfigurationScope;
import org.eclipse.core.runtime.preferences.DefaultScope;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.IScopeContext;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.emf.ecore.EReference;
import org.osgi.service.prefs.BackingStoreException;

import com._1c.g5.v8.dt.md.sort.MdSortPreferences;
import com.e1c.v8codestyle.internal.autosort.AutoSortPlugin;

/**
 * Public constants and utility method for sort preferences in the project.
 *
 * @author Dmitriy Marmyshev
 */
public final class AutoSortPreferences
{
    /**
     * @deprecated Use the parameter {@link MdSortPreferences#ASCENDING_SORT} instead.
     */
    @Deprecated(since = "0.5.0")
    public static final String KEY_ASCENDING = "sortAscending"; //$NON-NLS-1$

    /**
     * @deprecated Use the parameter {@link MdSortPreferences#NATURAL_SORT_ORDER} instead.
     */
    @Deprecated(since = "0.5.0")
    public static final String KEY_SORT_ORDER = "naturalSortOrder"; //$NON-NLS-1$

    public static final String KEY_ALL_TOP = "topObjects"; //$NON-NLS-1$

    public static final String KEY_TOP_NODE = "top"; //$NON-NLS-1$

    public static final String KEY_SUBORDINATE_OBJECTS = "subordinateObjects"; //$NON-NLS-1$

    public static final String KEY_SUBORDINATE_NODE = "subordinate"; //$NON-NLS-1$

    public static final String KEY_FORMS = CATALOG__FORMS.getName();

    public static final String KEY_TEMPLATES = CATALOG__TEMPLATES.getName();

    public static final String KEY_COMMANDS = CATALOG__COMMANDS.getName();

    public static final String KEY_OPERATIONS = WEB_SERVICE__OPERATIONS.getName();

    public static final String KEY_URL_TEMPLATES = HTTP_SERVICE__URL_TEMPLATES.getName();

    public static final String KEY_METHODS = URL_TEMPLATE__METHODS.getName();

    public static final String KEY_ATTRIBUTES = CATALOG__ATTRIBUTES.getName();

    public static final String KEY_REGISTRY_RESOURCES = INFORMATION_REGISTER__RESOURCES.getName();

    public static final String KEY_TABULAR_SECTIONS = CATALOG__TABULAR_SECTIONS.getName();

    /**
     * @deprecated Use the parameter {@link MdSortPreferences#DEFAULT_ASCENDING_SORT} instead.
     */
    @Deprecated(since = "0.5.0")
    public static final boolean DEFAULT_SORT_ASCENDING = true;

    public static final boolean DEFAULT_SORT = false;

    /**
     * @deprecated Use the parameter {@link MdSortPreferences#DEFAULT_NATURAL_SORT_ORDER} instead.
     */
    @Deprecated(since = "0.5.0")
    public static final boolean DEFAULT_SORT_ORDER = true;

    /**
     * Checks if the sort direction is ascending in the project.
     *
     * @param project the project to check, cannot be {@code null}.
     * @return true, if the sort is ascending, or return true as default if not set for project.
     * @deprecated Use the method {@link MdSortPreferences#isAscendingSort(IProject)} instead.
     */
    @Deprecated(since = "0.5.0")
    public static boolean isSortAscending(IProject project)
    {
        IEclipsePreferences rootNode = getPreferences(project);
        return rootNode.getBoolean(KEY_ASCENDING, DEFAULT_SORT_ASCENDING);
    }

    /**
     * Checks if the sort order natural or as designer in the project.
     *
     * @param project the project to check, cannot be {@code null}.
     * @return true, if the sort order is natural, or return true as default if not set for project.
     * @deprecated Use the method {@link MdSortPreferences#isNaturalSortOrder(IProject)} instead.
     */
    @Deprecated(since = "0.5.0")
    public static boolean isNaturalSortOrder(IProject project)
    {
        IEclipsePreferences rootNode = getPreferences(project);
        return rootNode.getBoolean(KEY_SORT_ORDER, DEFAULT_SORT_ORDER);
    }
    /**
     * Checks if need to sort all top object.
     *
     * @param project the project, cannot be {@code null}.
     * @return true, if need to sort all top object
     */
    public static boolean isSortAllTop(IProject project)
    {
        ProjectScope projectScope = new ProjectScope(project);
        IScopeContext[] contexts = new IScopeContext[] { projectScope, InstanceScope.INSTANCE,
            ConfigurationScope.INSTANCE, DefaultScope.INSTANCE };

        return Platform.getPreferencesService()
            .getBoolean(AutoSortPlugin.PLUGIN_ID, KEY_ALL_TOP, DEFAULT_SORT, contexts);
    }

    /**
     * Checks if need to sort sub-ordinate objects of the top object.
     *
     * @param project the project, cannot be {@code null}.
     * @return true, if need to sort sub-ordinate objects
     */
    public static boolean isSortSubOrdinateObjects(IProject project)
    {
        IEclipsePreferences rootNode = getPreferences(project);
        return rootNode.getBoolean(KEY_SUBORDINATE_OBJECTS, DEFAULT_SORT);
    }

    /**
     * Checks if it is allowed to sort the list reference in the project.
     *
     * @param project the project, cannot be {@code null}.
     * @param listRef the list reference, cannot be {@code null}.
     * @return true, if it is allowed to sort the list
     */
    public static boolean isAllowedToSort(IProject project, EReference listRef)
    {
        if (ListConstants.TOP_OPBJECT_LISTS.contains(listRef))
        {
            return isSortAllTop(project) || isSortTopList(project, listRef);
        }

        if (ListConstants.SUBORDINATE_OBJECT_LISTS.contains(listRef))
        {
            return isSortSubOrdinateObjects(project) || isSortSubordinateList(project, listRef);
        }

        return false;
    }

    /**
     * Gets the preferences for the project.
     *
     * @param project the project, cannot be {@code null}.
     * @return the preferences for the project, cannot return {@code null}.
     */
    public static IEclipsePreferences getPreferences(IProject project)
    {
        ProjectScope projectScope = new ProjectScope(project);
        IEclipsePreferences rootNode = projectScope.getNode(AutoSortPlugin.PLUGIN_ID);
        return rootNode;
    }

    /**
     * Setup the project default values.
     *
     * @param project the project to setup default, cannot be {@code null}.
     */
    public static void setupProjectDefault(IProject project)
    {
        IEclipsePreferences prefs = getPreferences(project);
        prefs.putBoolean(KEY_ALL_TOP, true);
        try
        {
            prefs.flush();
        }
        catch (BackingStoreException e)
        {
            AutoSortPlugin.logError(e);
        }
    }

    /**
     * Checks whether the auto sort is enabled for the specified project.
     *
     * @param project the project to check, cannot be {@code null}.
     * @return {@code true} if the auto sort is enabled for the project, {@code false otherwise}
     */
    public static boolean isAutoSortEnabled(IProject project)
    {
        if (isSortAllTop(project) || isSortSubOrdinateObjects(project))
        {
            return true;
        }
        for (EReference reference : ListConstants.TOP_OPBJECT_LISTS)
        {
            if (isSortTopList(project, reference))
            {
                return true;
            }
        }
        for (EReference reference : ListConstants.SUBORDINATE_OBJECT_LISTS)
        {
            if (isSortSubordinateList(project, reference))
            {
                return true;
            }
        }
        return false;
    }

    private static boolean isSortTopList(IProject project, EReference listRef)
    {
        IEclipsePreferences rootNode = getPreferences(project);
        return rootNode.node(KEY_TOP_NODE).getBoolean(listRef.getName(), DEFAULT_SORT);
    }

    private static boolean isSortSubordinateList(IProject project, EReference listRef)
    {
        IEclipsePreferences rootNode = getPreferences(project);
        return rootNode.node(KEY_SUBORDINATE_NODE).getBoolean(listRef.getName(), DEFAULT_SORT);
    }

    private AutoSortPreferences()
    {
        throw new IllegalAccessError("Utility class"); //$NON-NLS-1$
    }

}
