/*
 * Copyright 2020 Red Hat
 *
 * Licensed 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 io.apicurio.registry.rules.compatibility.jsonschema.diff;

import lombok.Getter;

/**
 * @author Jakub Senko 'jsenko@redhat.com'
 */
public enum DiffType {

    SUBSCHEMA_TYPE_CHANGED(false),
    SUBSCHEMA_TYPE_CHANGED_TO_EMPTY_OR_TRUE(true),

    OBJECT_TYPE_REQUIRED_PROPERTIES_ADDED(false),
    OBJECT_TYPE_REQUIRED_PROPERTIES_REMOVED(true),
    OBJECT_TYPE_REQUIRED_PROPERTIES_CHANGED(true),
    OBJECT_TYPE_REQUIRED_PROPERTIES_MEMBER_ADDED(false),
    OBJECT_TYPE_REQUIRED_PROPERTIES_MEMBER_REMOVED(true),

    OBJECT_TYPE_PROPERTY_SCHEMA_ADDED(false),
    OBJECT_TYPE_PROPERTY_SCHEMA_REMOVED(true),

    OBJECT_TYPE_MIN_PROPERTIES_ADDED(false),
    OBJECT_TYPE_MIN_PROPERTIES_REMOVED(true),
    OBJECT_TYPE_MIN_PROPERTIES_INCREASED(false),
    OBJECT_TYPE_MIN_PROPERTIES_DECREASED(true),

    OBJECT_TYPE_MAX_PROPERTIES_ADDED(false),
    OBJECT_TYPE_MAX_PROPERTIES_REMOVED(true),
    OBJECT_TYPE_MAX_PROPERTIES_INCREASED(true),
    OBJECT_TYPE_MAX_PROPERTIES_DECREASED(false),

    OBJECT_TYPE_ADDITIONAL_PROPERTIES_FALSE_TO_TRUE(true),
    OBJECT_TYPE_ADDITIONAL_PROPERTIES_TRUE_TO_FALSE(false),
    OBJECT_TYPE_ADDITIONAL_PROPERTIES_BOOLEAN_UNCHANGED(true),

    OBJECT_TYPE_ADDITIONAL_PROPERTIES_SCHEMA_ADDED(false),
    OBJECT_TYPE_ADDITIONAL_PROPERTIES_SCHEMA_REMOVED(true),

    OBJECT_TYPE_PROPERTY_DEPENDENCIES_KEYS_ADDED(false),
    OBJECT_TYPE_PROPERTY_DEPENDENCIES_KEYS_REMOVED(true),
    OBJECT_TYPE_PROPERTY_DEPENDENCIES_KEYS_CHANGED(true),
    OBJECT_TYPE_PROPERTY_DEPENDENCIES_KEYS_MEMBER_ADDED(false),
    OBJECT_TYPE_PROPERTY_DEPENDENCIES_KEYS_MEMBER_REMOVED(true),

    OBJECT_TYPE_PROPERTY_DEPENDENCIES_VALUE_MEMBER_CHANGED(true),
    OBJECT_TYPE_PROPERTY_DEPENDENCIES_VALUE_MEMBER_ADDED(false),
    OBJECT_TYPE_PROPERTY_DEPENDENCIES_VALUE_MEMBER_REMOVED(true),

    OBJECT_TYPE_SCHEMA_DEPENDENCIES_ADDED(false),
    OBJECT_TYPE_SCHEMA_DEPENDENCIES_REMOVED(true),
    OBJECT_TYPE_SCHEMA_DEPENDENCIES_CHANGED(true),
    OBJECT_TYPE_SCHEMA_DEPENDENCIES_MEMBER_ADDED(false),
    OBJECT_TYPE_SCHEMA_DEPENDENCIES_MEMBER_REMOVED(true),

    OBJECT_TYPE_PROPERTY_SCHEMAS_ADDED(false),
    OBJECT_TYPE_PROPERTY_SCHEMAS_REMOVED(true),
    OBJECT_TYPE_PROPERTY_SCHEMAS_CHANGED(true),
    OBJECT_TYPE_PROPERTY_SCHEMAS_MEMBER_ADDED(false),
    OBJECT_TYPE_PROPERTY_SCHEMAS_MEMBER_REMOVED(true),

    OBJECT_TYPE_PATTERN_PROPERTY_KEYS_ADDED(false),
    OBJECT_TYPE_PATTERN_PROPERTY_KEYS_REMOVED(true),
    OBJECT_TYPE_PATTERN_PROPERTY_KEYS_CHANGED(true),
    OBJECT_TYPE_PATTERN_PROPERTY_KEYS_MEMBER_ADDED(false),
    OBJECT_TYPE_PATTERN_PROPERTY_KEYS_MEMBER_REMOVED(true),


    ARRAY_TYPE_MIN_ITEMS_ADDED(false),
    ARRAY_TYPE_MIN_ITEMS_REMOVED(true),
    ARRAY_TYPE_MIN_ITEMS_INCREASED(false),
    ARRAY_TYPE_MIN_ITEMS_DECREASED(true),

    ARRAY_TYPE_MAX_ITEMS_ADDED(false),
    ARRAY_TYPE_MAX_ITEMS_REMOVED(true),
    ARRAY_TYPE_MAX_ITEMS_INCREASED(true),
    ARRAY_TYPE_MAX_ITEMS_DECREASED(false),

    ARRAY_TYPE_UNIQUE_ITEMS_FALSE_TO_TRUE(false),
    ARRAY_TYPE_UNIQUE_ITEMS_TRUE_TO_FALSE(true),
    ARRAY_TYPE_UNIQUE_ITEMS_BOOLEAN_UNCHANGED(true),

    ARRAY_TYPE_ADDITIONAL_ITEMS_FALSE_TO_TRUE(true),
    ARRAY_TYPE_ADDITIONAL_ITEMS_TRUE_TO_FALSE(false),
    ARRAY_TYPE_ADDITIONAL_ITEMS_BOOLEAN_UNCHANGED(true),
    ARRAY_TYPE_ADDITIONAL_ITEMS_EXTENDED(true),
    ARRAY_TYPE_ADDITIONAL_ITEMS_NARROWED(false),
    ARRAY_TYPE_SCHEMA_OF_ADDITIONAL_ITEMS_UNCHANGED(true),
    ARRAY_TYPE_SCHEMA_OF_ADDITIONAL_ITEMS_CHANGED(false),

    ARRAY_TYPE_ALL_ITEM_SCHEMA_ADDED(false),
    ARRAY_TYPE_ALL_ITEM_SCHEMA_REMOVED(true),

    ARRAY_TYPE_SCHEMA_OF_ADDITIONAL_ITEMS_ADDED(false),
    ARRAY_TYPE_SCHEMA_OF_ADDITIONAL_ITEMS_REMOVED(true),

    ARRAY_TYPE_CONTAINED_ITEMS_SCHEMA_ADDED(false),
    ARRAY_TYPE_CONTAINED_ITEMS_SCHEMA_REMOVED(true),

    ARRAY_TYPE_ITEMS_SCHEMAS_LENGTH_INCREASED(false),
    ARRAY_TYPE_ITEMS_SCHEMAS_LENGTH_DECREASED(false),

    ARRAY_TYPE_ITEMS_SCHEMA_ADDED(false),
    ARRAY_TYPE_ITEMS_SCHEMA_REMOVED(false), // TODO where
    ARRAY_TYPE_ITEMS_SCHEMA_EXTENDED(true),
    ARRAY_TYPE_ITEMS_SCHEMA_NARROWED(false),
    ARRAY_TYPE_ITEMS_SCHEMA_CHANGED(false),

    STRING_TYPE_MIN_LENGTH_ADDED(false),
    STRING_TYPE_MIN_LENGTH_REMOVED(true),
    STRING_TYPE_MIN_LENGTH_INCREASED(false),
    STRING_TYPE_MIN_LENGTH_DECREASED(true),

    STRING_TYPE_MAX_LENGTH_ADDED(false),
    STRING_TYPE_MAX_LENGTH_REMOVED(true),
    STRING_TYPE_MAX_LENGTH_INCREASED(true),
    STRING_TYPE_MAX_LENGTH_DECREASED(false),

    STRING_TYPE_PATTERN_ADDED(false),
    STRING_TYPE_PATTERN_REMOVED(true),
    STRING_TYPE_PATTERN_CHANGED(false),

    STRING_TYPE_FORMAT_ADDED(false),
    STRING_TYPE_FORMAT_REMOVED(true),
    STRING_TYPE_FORMAT_CHANGED(false),

    STRING_TYPE_CONTENT_ENCODING_ADDED(false),
    STRING_TYPE_CONTENT_ENCODING_REMOVED(true),
    STRING_TYPE_CONTENT_ENCODING_CHANGED(false),

    STRING_TYPE_CONTENT_MEDIA_TYPE_ADDED(false),
    STRING_TYPE_CONTENT_MEDIA_TYPE_REMOVED(true),
    STRING_TYPE_CONTENT_MEDIA_TYPE_CHANGED(false),


    CONST_TYPE_VALUE_CHANGED(false),


    ENUM_TYPE_VALUES_CHANGED(true),
    ENUM_TYPE_VALUES_MEMBER_ADDED(true),
    ENUM_TYPE_VALUES_MEMBER_REMOVED(false),


    NUMBER_TYPE_MINIMUM_ADDED(false),
    NUMBER_TYPE_MINIMUM_REMOVED(true),
    NUMBER_TYPE_MINIMUM_INCREASED(false),
    NUMBER_TYPE_MINIMUM_DECREASED(true),

    NUMBER_TYPE_IS_MINIMUM_EXCLUSIVE_FALSE_TO_TRUE(false),
    NUMBER_TYPE_IS_MINIMUM_EXCLUSIVE_TRUE_TO_FALSE(true),
    NUMBER_TYPE_IS_MINIMUM_EXCLUSIVE_UNCHANGED(true),

    NUMBER_TYPE_EXCLUSIVE_MINIMUM_ADDED(false),
    NUMBER_TYPE_EXCLUSIVE_MINIMUM_REMOVED(true),
    NUMBER_TYPE_EXCLUSIVE_MINIMUM_INCREASED(false),
    NUMBER_TYPE_EXCLUSIVE_MINIMUM_DECREASED(true),

    NUMBER_TYPE_MAXIMUM_ADDED(false),
    NUMBER_TYPE_MAXIMUM_REMOVED(true),
    NUMBER_TYPE_MAXIMUM_INCREASED(true),
    NUMBER_TYPE_MAXIMUM_DECREASED(false),

    NUMBER_TYPE_IS_MAXIMUM_EXCLUSIVE_FALSE_TO_TRUE(false),
    NUMBER_TYPE_IS_MAXIMUM_EXCLUSIVE_TRUE_TO_FALSE(true),
    NUMBER_TYPE_IS_MAXIMUM_EXCLUSIVE_UNCHANGED(true),

    NUMBER_TYPE_EXCLUSIVE_MAXIMUM_ADDED(false),
    NUMBER_TYPE_EXCLUSIVE_MAXIMUM_REMOVED(true),
    NUMBER_TYPE_EXCLUSIVE_MAXIMUM_INCREASED(true),
    NUMBER_TYPE_EXCLUSIVE_MAXIMUM_DECREASED(false),

    NUMBER_TYPE_MULTIPLE_OF_ADDED(false),
    NUMBER_TYPE_MULTIPLE_OF_REMOVED(true),
    NUMBER_TYPE_MULTIPLE_OF_UPDATED_IS_DIVISIBLE(true),
    NUMBER_TYPE_MULTIPLE_OF_UPDATED_IS_NOT_DIVISIBLE(false),

    NUMBER_TYPE_INTEGER_REQUIRED_FALSE_TO_TRUE(false),
    NUMBER_TYPE_INTEGER_REQUIRED_TRUE_TO_FALSE(true),
    NUMBER_TYPE_INTEGER_REQUIRED_UNCHANGED(true),

    COMBINED_TYPE_CRITERION_EXTENDED(true),
    COMBINED_TYPE_CRITERION_NARROWED(false),
    COMBINED_TYPE_CRITERION_CHANGED(false),

    COMBINED_TYPE_ONE_OF_SIZE_INCREASED(true), // As long as the existing subschemas maintain compatibility, checked separately.
    COMBINED_TYPE_ONE_OF_SIZE_DECREASED(false),

    COMBINED_TYPE_ALL_OF_SIZE_INCREASED(false),
    COMBINED_TYPE_ALL_OF_SIZE_DECREASED(true),

    COMBINED_TYPE_ANY_OF_SIZE_INCREASED(true), // As long as the existing subschemas maintain compatibility, checked separately.
    COMBINED_TYPE_ANY_OF_SIZE_DECREASED(false),

    COMBINED_TYPE_SUBSCHEMA_NOT_COMPATIBLE(false),


    CONDITIONAL_TYPE_IF_SCHEMA_ADDED(false),
    CONDITIONAL_TYPE_IF_SCHEMA_REMOVED(false),
    CONDITIONAL_TYPE_IF_SCHEMA_COMPATIBLE_BOTH(true),
    CONDITIONAL_TYPE_IF_SCHEMA_COMPATIBLE_BACKWARD_NOT_FORWARD(false),
    CONDITIONAL_TYPE_IF_SCHEMA_COMPATIBLE_FORWARD_NOT_BACKWARD(false),
    CONDITIONAL_TYPE_IF_SCHEMA_COMPATIBLE_NONE(false),

    CONDITIONAL_TYPE_THEN_SCHEMA_ADDED(false),
    CONDITIONAL_TYPE_THEN_SCHEMA_REMOVED(true),
    CONDITIONAL_TYPE_THEN_SCHEMA_COMPATIBLE_BOTH(true),
    CONDITIONAL_TYPE_THEN_SCHEMA_COMPATIBLE_BACKWARD_NOT_FORWARD(true),
    CONDITIONAL_TYPE_THEN_SCHEMA_COMPATIBLE_FORWARD_NOT_BACKWARD(false),
    CONDITIONAL_TYPE_THEN_SCHEMA_COMPATIBLE_NONE(false),

    CONDITIONAL_TYPE_ELSE_SCHEMA_ADDED(false),
    CONDITIONAL_TYPE_ELSE_SCHEMA_REMOVED(true),
    CONDITIONAL_TYPE_ELSE_SCHEMA_COMPATIBLE_BOTH(true),
    CONDITIONAL_TYPE_ELSE_SCHEMA_COMPATIBLE_BACKWARD_NOT_FORWARD(true),
    CONDITIONAL_TYPE_ELSE_SCHEMA_COMPATIBLE_FORWARD_NOT_BACKWARD(false),
    CONDITIONAL_TYPE_ELSE_SCHEMA_COMPATIBLE_NONE(false),

    REFERENCE_TYPE_TARGET_SCHEMA_ADDED(false),
    REFERENCE_TYPE_TARGET_SCHEMA_REMOVED(false), // TODO Would this cause validation error?


    NOT_TYPE_SCHEMA_COMPATIBLE_BOTH(true),
    NOT_TYPE_SCHEMA_COMPATIBLE_BACKWARD_NOT_FORWARD(false),
    NOT_TYPE_SCHEMA_COMPATIBLE_FORWARD_NOT_BACKWARD(true),
    NOT_TYPE_SCHEMA_COMPATIBLE_NONE(false),


    UNDEFINED_UNUSED(false); // Should not be used.


    @Getter
    private String description;

    @Getter
    private final boolean backwardsCompatible;

    DiffType(boolean backwardsCompatible) {
        this.description = this.toString();
        this.backwardsCompatible = backwardsCompatible;
    }

    DiffType(String description, boolean backwardsCompatible) {
        this(backwardsCompatible);
        this.description = description;
    }
}
