/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use flow_lint_settings::lints::LintKind;
use flow_lint_settings::lints::SketchyNullKind;
use flow_lint_settings::lints::SketchyNumberKind;

#[derive(
    Debug,
    Clone,
    Copy,
    PartialEq,
    Eq,
    Hash,
    PartialOrd,
    Ord,
    serde::Serialize,
    serde::Deserialize
)]
pub enum ErrorCode {
    AmbiguousObjectType,
    ReactRuleUnsafeMutation,
    ReactRuleHookConditional,
    ReactRuleHookDefinitelyNotInComponentOrHook,
    ReactRuleHookMixedWithNonHoook,
    ReactRuleHookMutation,
    ReactRuleHookNamingConvention,
    ReactRuleHookNonHookSyntax,
    ReactRuleHookIncompatible,
    ReactRuleHook,
    ReactRuleRef,
    ReactRuleCallComponent,
    CannotDelete,
    CannotImplement,
    CannotRead,
    CannotReassignConstLike,
    CannotResolveModule,
    CannotResolveName,
    CannotSpreadIndexer,
    CannotSpreadInexact,
    CannotSpreadInterface,
    CannotWrite,
    CannotWriteEnum,
    ClassObject,
    ComponentCase,
    ComponentMissingBody,
    ComponentMissingReturn,
    ComponentBodyInAmbientContext,
    ComponentThisReference,
    DefaultImportAccess,
    DeprecatedType,
    DeprecatedUtility,
    DuplicateClassMember,
    DuplicateEnumInit,
    DuplicateFlowDecl,
    DuplicateJsxDecl,
    DuplicateJsxRuntimeDecl,
    DuplicateModule,
    ElementAfterInexactTupleSpread,
    EmptyArrayNoAnnot,
    EnumValueAsType,
    ExponentialSpread,
    ExportRenamedDefault,
    ExportValueAsType,
    ExtraArg,
    ExtraTypeArg,
    FunctionPredicate,
    InvalidEnum,
    IllegalKey,
    IllegalNewArray,
    IllegalThis,
    IllegalTypeof,
    ImportTypeAsValue,
    ImportValueAsType,
    IncompatibleExact,
    IncompatibleFunctionIndexer,
    IncompatibleIndexer,
    IncompatibleType,
    IncompatibleTypeGuard,
    IncompatibleUse,
    IncompatibleVariance,
    InternalType,
    InvalidAbstract,
    InvalidOverride,
    InvalidCatchParameterAnnotation,
    InvalidCompare,
    InvalidComputedProp,
    InvalidConstructor,
    InvalidEnumAccess,
    InvalidEnumMemberName,
    InvalidExact,
    InvalidExhaustiveCheck,
    InvalidExport,
    InvalidExportsTypeArg,
    InvalidExtends,
    InvalidFlowModeDecl,
    InvalidGraphQL,
    InvalidExportedAnnotation,
    InvalidIdx,
    InvalidImportStarUse,
    InvalidImportType,
    InvalidSpreadProp,
    InvalidInfer,
    InvalidInLhs,
    InvalidInRhs,
    InvalidJsxDecl,
    InvalidJsxRuntimeDecl,
    InvalidLhs,
    InvalidMappedType,
    InvalidModule,
    InvalidTemplateLiteralType,
    InvalidPropType,
    InvalidReactCreateElement,
    InvalidRendersTypeArgument,
    InvalidSupportsPlatformDecl,
    InvalidTupleArity,
    InvalidTupleIndex,
    InvalidTypeArg,
    InvalidTypeCastSyntax,
    InvalidTypeOf,
    LibdefOverride,
    LintSetting,
    MalformedPackage,
    MatchInvalidPattern,
    MatchNotExhaustive,
    MatchStatementInvalidBody,
    MatchUnusedPattern,
    MethodUnbinding,
    MissingLocalAnnot,
    MissingThisAnnot,
    MissingArg,
    MissingExport,
    MissingPlatformSupport,
    MissingTypeArg,
    MixedImportAndRequire,
    ModuleTypeConflict,
    NameAlreadyBound,
    NonConstVarExport,
    NonpolymorphicTypeApp,
    NonpolymorphicTypeArg,
    NonstrictImport,
    NotAClass,
    NotAComponent,
    NotAFunction,
    NotAnArray,
    NotAnObject,
    NotIterable,
    ObjectThisReference,
    PropMissing,
    ReassignConst,
    ReassignEnum,
    ReassignImport,
    RecordBannedTypeUtil,
    RecordInvalidName,
    RecordInvalidNew,
    RecordInvalidSyntax,
    ReferenceBeforeDeclaration,
    RequireExplicitEnumChecks,
    RequireExplicitEnumSwitchCases,
    SignatureVerificationFailure,
    SketchyNullBool,
    SketchyNullMixed,
    SketchyNullNumber,
    SketchyNullString,
    SketchyNullBigInt,
    SketchyNumberAnd,
    ThisInExportedFunction,
    TupleInvalidTypeSpread,
    TupleRequiredAfterOptional,
    TypeAsValue,
    UnclearType,
    UnderconstrainedImplicitInstantiation,
    UndocumentedFeature,
    UninitializedInstanceProperty,
    UnionUnoptimizable,
    UnionPartiallyOptimizableNonUniqueKeys,
    UnnecessaryInvariant,
    UnnecessaryOptionalChain,
    UnnecessaryDeclareTypeOnlyExport,
    UnreachableCode,
    UnsafeAddition,
    UnsafeArith,
    UnsafeGettersSetters,
    UnsafeObjectAssign,
    UnsupportedSyntax,
    UnsupportedVarianceAnnotation,
    UntypedImport,
    UntypedTypeImport,
    ValueAsType,
    InvalidDeclaration,
    DefinitionCycle,
    RecursiveDefinition,
    LogicalAssignmentOperatorsNotSupported,
    UnusedPromise,
    BigIntRShift3,
    BigIntNumCoerce,
    InvalidComponentProp,
    ReactIntrinsicOverlap,
    NestedComponent,
    NestedHook,
    TypeParamConstCode,
    IllegalAssertOperator,
    ConstantCondition,
    ReservedKeyword,
}

pub fn code_of_lint(lint_kind: &LintKind) -> ErrorCode {
    use LintKind::*;
    match lint_kind {
        ReactIntrinsicOverlap => ErrorCode::ReactIntrinsicOverlap,
        NestedComponent => ErrorCode::NestedComponent,
        NestedHook => ErrorCode::NestedHook,
        UntypedTypeImport => ErrorCode::UntypedTypeImport,
        UntypedImport => ErrorCode::UntypedImport,
        NonstrictImport => ErrorCode::NonstrictImport,
        InternalType => ErrorCode::InternalType,
        UnclearType => ErrorCode::UnclearType,
        DeprecatedType(_) => ErrorCode::DeprecatedType,
        UnsafeGettersSetters => ErrorCode::UnsafeGettersSetters,
        UnsafeObjectAssign => ErrorCode::UnsafeObjectAssign,
        UnnecessaryOptionalChain => ErrorCode::UnnecessaryOptionalChain,
        UnnecessaryInvariant => ErrorCode::UnnecessaryInvariant,
        UninitializedInstanceProperty => ErrorCode::UninitializedInstanceProperty,
        AmbiguousObjectType => ErrorCode::AmbiguousObjectType,
        RequireExplicitEnumChecks => ErrorCode::RequireExplicitEnumChecks,
        RequireExplicitEnumSwitchCases => ErrorCode::RequireExplicitEnumSwitchCases,
        SketchyNumber(SketchyNumberKind::And) => ErrorCode::SketchyNumberAnd,
        SketchyNull(SketchyNullKind::Bool | SketchyNullKind::EnumBool) => {
            ErrorCode::SketchyNullBool
        }
        SketchyNull(SketchyNullKind::String | SketchyNullKind::EnumString) => {
            ErrorCode::SketchyNullString
        }
        SketchyNull(SketchyNullKind::Number | SketchyNullKind::EnumNumber) => {
            ErrorCode::SketchyNullNumber
        }
        SketchyNull(SketchyNullKind::BigInt | SketchyNullKind::EnumBigInt) => {
            ErrorCode::SketchyNullBigInt
        }
        SketchyNull(SketchyNullKind::Mixed) => ErrorCode::SketchyNullMixed,
        DefaultImportAccess => ErrorCode::DefaultImportAccess,
        InvalidImportStarUse => ErrorCode::InvalidImportStarUse,
        NonConstVarExport => ErrorCode::NonConstVarExport,
        ThisInExportedFunction => ErrorCode::ThisInExportedFunction,
        MixedImportAndRequire => ErrorCode::MixedImportAndRequire,
        ExportRenamedDefault => ErrorCode::ExportRenamedDefault,
        UnusedPromise => ErrorCode::UnusedPromise,
        LibdefOverride => ErrorCode::LibdefOverride,
    }
}

impl ErrorCode {
    pub fn as_str(self) -> &'static str {
        use ErrorCode::*;
        match self {
            ReactRuleUnsafeMutation => "react-rule-unsafe-mutation",
            ReactRuleHookConditional => "react-rule-hook-conditional",
            ReactRuleHookDefinitelyNotInComponentOrHook => {
                "react-rule-hook-definitely-not-in-component-or-hook"
            }
            ReactRuleHookMixedWithNonHoook => "react-rule-hook-mixed-with-non-hook",
            ReactRuleHookMutation => "react-rule-hook-mutation",
            ReactRuleHookNamingConvention => "react-rule-hook-naming-convention",
            ReactRuleHookNonHookSyntax => "react-rule-hook-non-hook-syntax",
            ReactRuleHookIncompatible => "react-rule-hook-incompatible",
            ReactRuleHook => "react-rule-hook",
            ReactRuleRef => "react-rule-unsafe-ref",
            ReactRuleCallComponent => "react-rule-call-component",
            AmbiguousObjectType => "ambiguous-object-type",
            CannotDelete => "cannot-delete",
            CannotImplement => "cannot-implement",
            CannotRead => "cannot-read",
            CannotReassignConstLike => "cannot-reassign",
            CannotResolveModule => "cannot-resolve-module",
            CannotResolveName => "cannot-resolve-name",
            CannotSpreadIndexer => "cannot-spread-indexer",
            CannotSpreadInexact => "cannot-spread-inexact",
            CannotSpreadInterface => "cannot-spread-interface",
            CannotWrite => "cannot-write",
            CannotWriteEnum => "cannot-write-enum",
            ClassObject => "class-object-subtyping",
            ComponentThisReference => "component-this-reference",
            ComponentCase => "component-case",
            ComponentMissingBody => "component-missing-body",
            ComponentMissingReturn => "component-missing-return",
            ComponentBodyInAmbientContext => "component-body-in-ambient-context",
            DefaultImportAccess => "default-import-access",
            DeprecatedType => "deprecated-type",
            DeprecatedUtility => "deprecated-utility",
            DuplicateClassMember => "duplicate-class-member",
            EmptyArrayNoAnnot => "missing-empty-array-annot",
            DuplicateEnumInit => "duplicate-enum-init",
            DuplicateFlowDecl => "duplicate-flow-decl",
            DuplicateJsxDecl => "duplicate-jsx-decl",
            DuplicateJsxRuntimeDecl => "duplicate-jsx-runtime-decl",
            DuplicateModule => "duplicate-module",
            ElementAfterInexactTupleSpread => "element-after-inexact-tuple-spread",
            EnumValueAsType => "enum-value-as-type",
            ExponentialSpread => "exponential-spread",
            ExportRenamedDefault => "export-renamed-default",
            ExportValueAsType => "export-value-as-type",
            ExtraArg => "extra-arg",
            ExtraTypeArg => "extra-type-arg",
            FunctionPredicate => "function-predicate",
            InvalidEnum => "invalid-enum",
            IllegalKey => "illegal-key",
            IllegalNewArray => "illegal-new-array",
            IllegalThis => "illegal-this",
            IllegalTypeof => "illegal-typeof",
            ImportTypeAsValue => "import-type-as-value",
            ImportValueAsType => "import-value-as-type",
            IncompatibleExact => "incompatible-exact",
            IncompatibleFunctionIndexer => "incompatible-function-indexer",
            IncompatibleIndexer => "incompatible-indexer",
            IncompatibleType => "incompatible-type",
            IncompatibleTypeGuard => "incompatible-type-guard",
            IncompatibleUse => "incompatible-use",
            IncompatibleVariance => "incompatible-variance",
            InternalType => "internal-type",
            InvalidAbstract => "invalid-abstract",
            InvalidOverride => "invalid-override",
            InvalidCatchParameterAnnotation => "invalid-catch-parameter-annotation",
            InvalidCompare => "invalid-compare",
            InvalidComputedProp => "invalid-computed-prop",
            InvalidConstructor => "invalid-constructor",
            InvalidEnumAccess => "invalid-enum-access",
            InvalidEnumMemberName => "invalid-enum-member-name",
            InvalidExact => "invalid-exact",
            InvalidExhaustiveCheck => "invalid-exhaustive-check",
            InvalidExport => "invalid-export",
            InvalidExportsTypeArg => "invalid-exports-type-arg",
            InvalidFlowModeDecl => "invalid-flow-mode",
            InvalidGraphQL => "invalid-graphql",
            InvalidExportedAnnotation => "invalid-exported-annotation",
            InvalidExtends => "invalid-extends",
            InvalidIdx => "invalid-idx",
            InvalidImportStarUse => "invalid-import-star-use",
            InvalidImportType => "invalid-import-type",
            InvalidSpreadProp => "invalid-spread-prop",
            InvalidInfer => "invalid-infer",
            InvalidInLhs => "invalid-in-lhs",
            InvalidInRhs => "invalid-in-rhs",
            InvalidJsxDecl => "invalid-jsx-decl",
            InvalidJsxRuntimeDecl => "invalid-jsx-runtime-decl",
            InvalidLhs => "invalid-lhs",
            InvalidMappedType => "invalid-mapped-type",
            InvalidModule => "invalid-module",
            InvalidTemplateLiteralType => "invalid-template-literal-type",
            InvalidPropType => "invalid-prop-type",
            InvalidReactCreateElement => "invalid-react-create-element",
            InvalidRendersTypeArgument => "invalid-render",
            InvalidSupportsPlatformDecl => "invalid-supports-platform",
            InvalidTupleArity => "invalid-tuple-arity",
            InvalidTupleIndex => "invalid-tuple-index",
            InvalidTypeArg => "invalid-type-arg",
            InvalidTypeCastSyntax => "invalid-type-cast-syntax",
            InvalidTypeOf => "invalid-typeof",
            LibdefOverride => "libdef-override",
            LintSetting => "lint-setting",
            MalformedPackage => "malformed-package",
            MatchInvalidPattern => "match-invalid-pattern",
            MatchNotExhaustive => "match-not-exhaustive",
            MatchStatementInvalidBody => "match-statement-invalid-body",
            MatchUnusedPattern => "match-unused-pattern",
            MethodUnbinding => "method-unbinding",
            MissingLocalAnnot => "missing-local-annot",
            MissingThisAnnot => "missing-this-annot",
            MissingArg => "missing-arg",
            MissingExport => "missing-export",
            MissingPlatformSupport => "missing-platform-support",
            MissingTypeArg => "missing-type-arg",
            MixedImportAndRequire => "mixed-import-and-require",
            ModuleTypeConflict => "module-type-conflict",
            NameAlreadyBound => "name-already-bound",
            NonConstVarExport => "non-const-var-export",
            NonpolymorphicTypeApp => "nonpolymorphic-type-app",
            NonpolymorphicTypeArg => "nonpolymorphic-type-arg",
            NonstrictImport => "nonstrict-import",
            NotAClass => "not-a-class",
            NotAComponent => "not-a-component",
            NotAFunction => "not-a-function",
            NotAnArray => "not-an-array",
            NotAnObject => "not-an-object",
            NotIterable => "not-iterable",
            ObjectThisReference => "object-this-reference",
            PropMissing => "prop-missing",
            ReassignConst => "reassign-const",
            ReassignEnum => "reassign-enum",
            ReassignImport => "reassign-import",
            RecordBannedTypeUtil => "record-banned-type-util",
            RecordInvalidName => "record-invalid-name",
            RecordInvalidNew => "record-invalid-new",
            RecordInvalidSyntax => "record-invalid-syntax",
            ReferenceBeforeDeclaration => "reference-before-declaration",
            RequireExplicitEnumChecks => "require-explicit-enum-checks",
            RequireExplicitEnumSwitchCases => "require-explicit-enum-switch-cases",
            SignatureVerificationFailure => "signature-verification-failure",
            SketchyNullBool => "sketchy-null-bool",
            SketchyNullMixed => "sketchy-null-mixed",
            SketchyNullNumber => "sketchy-null-number",
            SketchyNullBigInt => "sketchy-null-bigint",
            SketchyNullString => "sketchy-null-string",
            SketchyNumberAnd => "sketchy-number-and",
            ThisInExportedFunction => "this-in-exported-function",
            TupleInvalidTypeSpread => "tuple-invalid-type-spread",
            TupleRequiredAfterOptional => "tuple-required-after-optional",
            TypeAsValue => "type-as-value",
            UnclearType => "unclear-type",
            UnderconstrainedImplicitInstantiation => "underconstrained-implicit-instantiation",
            UndocumentedFeature => "undocumented-feature",
            UninitializedInstanceProperty => "uninitialized-instance-property",
            UnionUnoptimizable => "union-unoptimizable",
            UnionPartiallyOptimizableNonUniqueKeys => "union-partially-optimizable-non-unique-keys",
            UnnecessaryInvariant => "unnecessary-invariant",
            UnnecessaryOptionalChain => "unnecessary-optional-chain",
            UnnecessaryDeclareTypeOnlyExport => "unnecessary-declare-type-only-export",
            UnreachableCode => "unreachable-code",
            UnsafeAddition => "unsafe-addition",
            UnsafeArith => "unsafe-arithmetic",
            UnsafeGettersSetters => "unsafe-getters-setters",
            UnsafeObjectAssign => "unsafe-object-assign",
            UnsupportedSyntax => "unsupported-syntax",
            UnsupportedVarianceAnnotation => "unsupported-variance-annotation",
            UntypedImport => "untyped-import",
            UntypedTypeImport => "untyped-type-import",
            ValueAsType => "value-as-type",
            InvalidDeclaration => "invalid-declaration",
            DefinitionCycle => "definition-cycle",
            RecursiveDefinition => "recursive-definition",
            LogicalAssignmentOperatorsNotSupported => "logical-assignment-operators-not-supported",
            UnusedPromise => "unused-promise",
            ReactIntrinsicOverlap => "react-intrinsic-overlap",
            NestedComponent => "nested-component",
            NestedHook => "nested-hook",
            BigIntRShift3 => "bigint-unsigned-right-shift",
            BigIntNumCoerce => "bigint-num-coerce",
            InvalidComponentProp => "invalid-component-prop",
            TypeParamConstCode => "incompatible-type-param-const",
            IllegalAssertOperator => "illegal-assert-operator",
            ConstantCondition => "constant-condition",
            ReservedKeyword => "reserved-keyword",
        }
    }
}
