package com.databricks.labs.remorph.parsers.snowflake

import com.databricks.labs.remorph.parsers.snowflake.SnowflakeFunctionConverters.SynonymOf
import com.databricks.labs.remorph.parsers.{ConversionStrategy, FunctionBuilder, FunctionDefinition, intermediate => ir}

class SnowflakeFunctionBuilder extends FunctionBuilder {

  private val SnowflakeFunctionDefinitionPf: PartialFunction[String, FunctionDefinition] = {

    case "ABS" => FunctionDefinition.standard(1)
    case "ACOS" => FunctionDefinition.standard(1)
    case "ACOSH" => FunctionDefinition.standard(1)
    case "ADD_MONTHS" => FunctionDefinition.standard(2)
    case "ALERT_HISTORY" => FunctionDefinition.standard(4)
    case "ALL_USER_NAMES" => FunctionDefinition.standard(0)
    case "ANY_VALUE" => FunctionDefinition.standard(1)
    case "APPLICATION_JSON" => FunctionDefinition.standard(1)
    case "APPROXIMATE_JACCARD_INDEX" => FunctionDefinition.standard(1)
    case "APPROXIMATE_SIMILARITY" => FunctionDefinition.standard(1)
    case "APPROX_COUNT_DISTINCT" => FunctionDefinition.standard(1, Int.MaxValue)
    case "APPROX_PERCENTILE" => FunctionDefinition.standard(2)
    case "APPROX_PERCENTILE_ACCUMULATE" => FunctionDefinition.standard(1)
    case "APPROX_PERCENTILE_COMBINE" => FunctionDefinition.standard(1)
    case "APPROX_PERCENTILE_ESTIMATE" => FunctionDefinition.standard(2)
    case "APPROX_TOP_K" => FunctionDefinition.standard(1, 3)
    case "APPROX_TOP_K_ACCUMULATE" => FunctionDefinition.standard(2)
    case "APPROX_TOP_K_COMBINE" => FunctionDefinition.standard(1, 2)
    case "APPROX_TOP_K_ESTIMATE" => FunctionDefinition.standard(2)
    case "ARRAYS_OVERLAP" => FunctionDefinition.standard(2)
    case "ARRAYS_TO_OBJECT" => FunctionDefinition.standard(2)
    case "ARRAYAGG" => FunctionDefinition.standard(1).withConversionStrategy(SynonymOf("ARRAY_AGG"))
    case "ARRAY_AGG" => FunctionDefinition.standard(1)
    case "ARRAY_APPEND" => FunctionDefinition.standard(2)
    case "ARRAY_CAT" => FunctionDefinition.standard(2)
    case "ARRAY_COMPACT" => FunctionDefinition.standard(1)
    case "ARRAY_CONSTRUCT" => FunctionDefinition.standard(0, Int.MaxValue)
    case "ARRAY_CONSTRUCT_COMPACT" => FunctionDefinition.standard(0, Int.MaxValue)
    case "ARRAY_CONTAINS" => FunctionDefinition.standard(2)
    case "ARRAY_DISTINCT" => FunctionDefinition.standard(1)
    case "ARRAY_EXCEPT" => FunctionDefinition.standard(2)
    case "ARRAY_FLATTEN" => FunctionDefinition.standard(1)
    case "ARRAY_GENERATE_RANGE" => FunctionDefinition.standard(2, 3)
    case "ARRAY_INSERT" => FunctionDefinition.standard(3)
    case "ARRAY_INTERSECTION" => FunctionDefinition.standard(2)
    case "ARRAY_MAX" => FunctionDefinition.standard(1)
    case "ARRAY_MIN" => FunctionDefinition.standard(1)
    case "ARRAY_POSITION" => FunctionDefinition.standard(2)
    case "ARRAY_PREPEND" => FunctionDefinition.standard(2)
    case "ARRAY_REMOVE" => FunctionDefinition.standard(2)
    case "ARRAY_REMOVE_AT" => FunctionDefinition.standard(2)
    case "ARRAY_SIZE" => FunctionDefinition.standard(1)
    case "ARRAY_SLICE" => FunctionDefinition.standard(3)
    case "ARRAY_SORT" => FunctionDefinition.standard(1, 3)
    case "ARRAY_TO_STRING" => FunctionDefinition.standard(2)
    case "ARRAY_UNION_AGG" => FunctionDefinition.standard(1)
    case "ARRAY_UNIQUE_AGG" => FunctionDefinition.standard(1)
    case "ASCII" => FunctionDefinition.standard(1)
    case "ASIN" => FunctionDefinition.standard(1)
    case "ASINH" => FunctionDefinition.standard(1)
    case "AS_ARRAY" => FunctionDefinition.standard(1)
    case "AS_BINARY" => FunctionDefinition.standard(1)
    case "AS_BOOLEAN" => FunctionDefinition.standard(1)
    case "AS_CHAR" => FunctionDefinition.standard(1)
    case "AS_DATE" => FunctionDefinition.standard(1)
    case "AS_DECIMAL" => FunctionDefinition.standard(1, 3)
    case "AS_DOUBLE" => FunctionDefinition.standard(1)
    case "AS_INTEGER" => FunctionDefinition.standard(1)
    case "AS_NUMBER" => FunctionDefinition.standard(1, 3)
    case "AS_OBJECT" => FunctionDefinition.standard(1)
    case "AS_REAL" => FunctionDefinition.standard(1)
    case "AS_TIME" => FunctionDefinition.standard(1)
    case "AS_TIMESTAMP_LTZ" => FunctionDefinition.standard(1)
    case "AS_TIMESTAMP_NTZ" => FunctionDefinition.standard(1)
    case "AS_TIMESTAMP_TZ" => FunctionDefinition.standard(1)
    case "AS_VARCHAR" => FunctionDefinition.standard(1)
    case "ATAN" => FunctionDefinition.standard(1)
    case "ATAN2" => FunctionDefinition.standard(2)
    case "ATANH" => FunctionDefinition.standard(1)
    case "AUTOMATIC_CLUSTERING_HISTORY" =>
      FunctionDefinition.symbolic(Set.empty, Set("DATE_RANGE_START", "DATE_RANGE_END", "TABLE_NAME"))
    case "AUTO_REFRESH_REGISTRATION_HISTORY" =>
      FunctionDefinition.symbolic(Set.empty, Set("DATE_RANGE_START", "DATE_RANGE_END", "OBJECT_TYPE", "OBJECT_NAME"))
    case "AVG" => FunctionDefinition.standard(1)
    case "BASE64_DECODE_BINARY" => FunctionDefinition.standard(1, 2)
    case "BASE64_DECODE_STRING" => FunctionDefinition.standard(1, 2)
    case "BASE64_ENCODE" => FunctionDefinition.standard(1, 3)
    case "BITAND" => FunctionDefinition.standard(2, 3)
    case "BITAND_AGG" => FunctionDefinition.standard(1)
    case "BITMAP_BIT_POSITION" => FunctionDefinition.standard(1)
    case "BITMAP_BUCKET_NUMBER" => FunctionDefinition.standard(1)
    case "BITMAP_CONSTRUCT_AGG" => FunctionDefinition.standard(1)
    case "BITMAP_COUNT" => FunctionDefinition.standard(1)
    case "BITMAP_OR_AGG" => FunctionDefinition.standard(1)
    case "BITNOT" => FunctionDefinition.standard(1)
    case "BITOR" => FunctionDefinition.standard(2, 3)
    case "BITOR_AGG" => FunctionDefinition.standard(1)
    case "BITSHIFTLEFT" => FunctionDefinition.standard(2)
    case "BITSHIFTRIGHT" => FunctionDefinition.standard(2)
    case "BITXOR" => FunctionDefinition.standard(2, 3)
    case "BITXOR_AGG" => FunctionDefinition.standard(1)
    case "BIT_LENGTH" => FunctionDefinition.standard(1)
    case "BLANK_COUNT (system data metric function)" => FunctionDefinition.standard(1)
    case "BLANK_PERCENT (system data metric function)" => FunctionDefinition.standard(1)
    case "BOOLAND" => FunctionDefinition.standard(2)
    case "BOOLAND_AGG" => FunctionDefinition.standard(1)
    case "BOOLNOT" => FunctionDefinition.standard(1)
    case "BOOLOR" => FunctionDefinition.standard(2)
    case "BOOLOR_AGG" => FunctionDefinition.standard(1)
    case "BOOLXOR" => FunctionDefinition.standard(2)
    case "BOOLXOR_AGG" => FunctionDefinition.standard(1)
    case "BUILD_SCOPED_FILE_URL" => FunctionDefinition.standard(0)
    case "BUILD_STAGE_FILE_URL" => FunctionDefinition.standard(0)
    case "CAST , " => FunctionDefinition.standard(2)
    case "CBRT" => FunctionDefinition.symbolic(Set("STR"), Set("DISABLE_AUTO_CONVERT"))
    case "CEIL" => FunctionDefinition.standard(1, 2)
    case "CHAR" => FunctionDefinition.standard(1)
    case "CHARINDEX" => FunctionDefinition.standard(2, 3)
    case "CHECK_JSON" => FunctionDefinition.standard(1)
    case "CHECK_XML" => FunctionDefinition.symbolic(Set("STR"), Set("DISABLE_AUTO_CONVERT"))
    case "CHR" => FunctionDefinition.standard(1)
    case "COALESCE" => FunctionDefinition.standard(1, Int.MaxValue)
    case "COLLATE" => FunctionDefinition.standard(2)
    case "COLLATION" => FunctionDefinition.standard(1)
    case "COMPLETE (SNOWFLAKE.CORTEX)" => FunctionDefinition.standard(2, 3)
    case "COMPLETE_TASK_GRAPHS" =>
      FunctionDefinition.symbolic(Set.empty, Set("RESULT_LIMIT", "ROOT_TASK_NAME", "ERROR_ONLY"))
    case "COMPRESS" => FunctionDefinition.standard(2)
    case "CONCAT , " => FunctionDefinition.standard(1)
    case "CONCAT_WS" => FunctionDefinition.standard(1, Int.MaxValue)
    case "CONDITIONAL_CHANGE_EVENT" => FunctionDefinition.standard(1)
    case "CONDITIONAL_TRUE_EVENT" => FunctionDefinition.standard(1)
    case "CONTAINS" => FunctionDefinition.standard(2)
    case "CONVERT_TIMEZONE" => FunctionDefinition.standard(2, 3)
    case "COPY_HISTORY" => FunctionDefinition.standard(2, 3)
    case "CORR" => FunctionDefinition.standard(2)
    case "COS" => FunctionDefinition.standard(1)
    case "COSH" => FunctionDefinition.standard(1)
    case "COT" => FunctionDefinition.standard(1)
    case "COUNT" => FunctionDefinition.standard(1, Int.MaxValue)
    case "COUNT_IF" => FunctionDefinition.standard(1)
    case "COUNT_TOKENS (SNOWFLAKE.CORTEX)" => FunctionDefinition.standard(3)
    case "COVAR_POP" => FunctionDefinition.standard(2)
    case "COVAR_SAMP" => FunctionDefinition.standard(2)
    case "CUME_DIST" => FunctionDefinition.standard(0)
    case "CURRENT_ACCOUNT" => FunctionDefinition.standard(0)
    case "CURRENT_ACCOUNT_NAME" => FunctionDefinition.standard(0)
    case "CURRENT_AVAILABLE_ROLES" => FunctionDefinition.standard(0)
    case "CURRENT_CLIENT" => FunctionDefinition.standard(0)
    case "CURRENT_DATABASE" => FunctionDefinition.standard(0)
    case "CURRENT_DATE" => FunctionDefinition.standard(0)
    case "CURRENT_IP_ADDRESS" => FunctionDefinition.standard(0)
    case "CURRENT_ORGANIZATION_NAME" => FunctionDefinition.standard(0)
    case "CURRENT_REGION" => FunctionDefinition.standard(0)
    case "CURRENT_ROLE" => FunctionDefinition.standard(0)
    case "CURRENT_ROLE_TYPE" => FunctionDefinition.standard(0)
    case "CURRENT_SCHEMA" => FunctionDefinition.standard(0)
    case "CURRENT_SCHEMAS" => FunctionDefinition.standard(0)
    case "CURRENT_SECONDARY_ROLES" => FunctionDefinition.standard(0)
    case "CURRENT_SESSION" => FunctionDefinition.standard(0)
    case "CURRENT_STATEMENT" => FunctionDefinition.standard(0)
    case "CURRENT_TASK_GRAPHS" => FunctionDefinition.symbolic(Set.empty, Set("RESULT_LIMIT", "ROOT_TASK_NAME"))
    case "CURRENT_TIME" => FunctionDefinition.standard(0, 1)
    case "CURRENT_TIMESTAMP" => FunctionDefinition.standard(0, 1)
    case "CURRENT_TRANSACTION" => FunctionDefinition.standard(0)
    case "CURRENT_USER" => FunctionDefinition.standard(0)
    case "CURRENT_VERSION" => FunctionDefinition.standard(0)
    case "CURRENT_WAREHOUSE" => FunctionDefinition.standard(0)
    case "DATABASE_REFRESH_HISTORY" => FunctionDefinition.standard(0, 1)
    case "DATABASE_REFRESH_PROGRESS" => FunctionDefinition.standard(0, 1)
    case "DATABASE_REFRESH_PROGRESS_BY_JOB" => FunctionDefinition.standard(0, 1)
    case "DATABASE_REPLICATION_USAGE_HISTORY" =>
      FunctionDefinition.symbolic(Set.empty, Set("DATE_RANGE_START", "DATE_RANGE_END", "DATABASE_NAME"))
    case "DATABASE_STORAGE_USAGE_HISTORY" =>
      FunctionDefinition.symbolic(Set.empty, Set("DATE_RANGE_START", "DATE_RANGE_END", "DATABASE_NAME"))
    case "DATA_METRIC_FUNCTION_REFERENCES" => FunctionDefinition.standard(3)
    case "DATA_METRIC_SCHEDULED_TIME (system data metric function)" => FunctionDefinition.standard(0)
    case "DATA_TRANSFER_HISTORY" => FunctionDefinition.symbolic(Set.empty, Set("DATE_RANGE_START", "DATE_RANGE_END"))
    case "DATE" => FunctionDefinition.standard(1, 2).withConversionStrategy(SynonymOf("TO_DATE"))
    case "DATEADD" => FunctionDefinition.standard(3)
    case "DATEDIFF" => FunctionDefinition.standard(3)
    case "DATEFROMPARTS" => FunctionDefinition.standard(3).withConversionStrategy(SynonymOf("DATE_FROM_PARTS"))
    case "DATE_FROM_PARTS" => FunctionDefinition.standard(3)
    case "DATE_PART" => FunctionDefinition.standard(2)
    case "DATE_TRUNC" => FunctionDefinition.standard(2)
    case "DAY" => FunctionDefinition.standard(1)
    case "DAYNAME" => FunctionDefinition.standard(1)
    case "DAYOFMONTH" => FunctionDefinition.standard(1)
    case "DAYOFWEEK" => FunctionDefinition.standard(1)
    case "DAYOFWEEKISO" => FunctionDefinition.standard(1)
    case "DAYOFYEAR" => FunctionDefinition.standard(1)
    case "DECODE" => FunctionDefinition.standard(3, Int.MaxValue)
    case "DECOMPRESS_BINARY" => FunctionDefinition.standard(2)
    case "DECOMPRESS_STRING" => FunctionDefinition.standard(2)
    case "DECRYPT" => FunctionDefinition.standard(2, 4)
    case "DECRYPT_RAW" => FunctionDefinition.standard(3, 6)
    case "DEGREES" => FunctionDefinition.standard(1)
    case "DENSE_RANK" => FunctionDefinition.standard(0)
    case "DIV0" => FunctionDefinition.standard(2)
    case "DIV0NULL" => FunctionDefinition.standard(2)
    case "DUPLICATE_COUNT (system data metric function)" => FunctionDefinition.standard(1)
    case "DYNAMIC_TABLES" => FunctionDefinition.standard(3)
    case "DYNAMIC_TABLE_GRAPH_HISTORY" =>
      FunctionDefinition.symbolic(Set.empty, Set("AS_OF", "HISTORY_START", "HISTORY_END"))
    case "DYNAMIC_TABLE_REFRESH_HISTORY" =>
      FunctionDefinition.symbolic(
        Set.empty,
        Set("DATA_TIMESTAMP_START", "DATA_TIMESTAMP_END", "RESULT_LIMIT", "NAME", "NAME_PREFIX", "ERROR_ONLY"))
    case "EDITDISTANCE" => FunctionDefinition.standard(2, 3)
    case "EMAIL_INTEGRATION_CONFIG" => FunctionDefinition.standard(5)
    case "EMBED_TEXT_1024 (SNOWFLAKE.CORTEX)" => FunctionDefinition.standard(2)
    case "EMBED_TEXT_768 (SNOWFLAKE.CORTEX)" => FunctionDefinition.standard(2)
    case "ENCRYPT" => FunctionDefinition.standard(2, 4)
    case "ENCRYPT_RAW" => FunctionDefinition.standard(3, 5)
    case "ENDSWITH" => FunctionDefinition.standard(2)
    case "EQUAL_NULL" => FunctionDefinition.standard(2)
    case "EXP" => FunctionDefinition.standard(1)
    case "EXPLAIN_JSON" => FunctionDefinition.standard(1)
    case "EXTERNAL_FUNCTIONS_HISTORY" =>
      FunctionDefinition.symbolic(Set.empty, Set("DATE_RANGE_START", "DATE_RANGE_END", "FUNCTION_SIGNATURE"))
    case "EXTERNAL_TABLE_FILES" => FunctionDefinition.standard(1)
    case "EXTERNAL_TABLE_FILE_REGISTRATION_HISTORY" => FunctionDefinition.standard(1, 2)
    case "EXTRACT" => FunctionDefinition.standard(2)
    case "EXTRACT_ANSWER (SNOWFLAKE.CORTEX)" => FunctionDefinition.standard(2)
    case "EXTRACT_SEMANTIC_CATEGORIES" => FunctionDefinition.standard(1, 2)
    case "FACTORIAL" => FunctionDefinition.standard(1)
    case "FILTER" => FunctionDefinition.standard(2)
    case "FINETUNE ('CANCEL') (SNOWFLAKE.CORTEX)" => FunctionDefinition.standard(0)
    case "FINETUNE ('CREATE') (SNOWFLAKE.CORTEX)" => FunctionDefinition.standard(0)
    case "FINETUNE ('DESCRIBE') (SNOWFLAKE.CORTEX)" => FunctionDefinition.standard(0)
    case "FINETUNE ('SHOW') (SNOWFLAKE.CORTEX)" => FunctionDefinition.standard(0)
    case "FINETUNE (SNOWFLAKE.CORTEX)" => FunctionDefinition.standard(0)
    case "FIRST_VALUE" => FunctionDefinition.standard(1)
    case "FLATTEN" => FunctionDefinition.symbolic(Set("INPUT"), Set("PATH", "OUTER", "RECURSIVE", "MODE"))
    case "FLOOR" => FunctionDefinition.standard(1, 2)
    case "FRESHNESS (system data metric function)" => FunctionDefinition.standard(1)
    case "GENERATE_COLUMN_DESCRIPTION" => FunctionDefinition.standard(2)
    case "GENERATOR" => FunctionDefinition.symbolic(Set.empty, Set("ROWCOUNT", "TIMELIMIT"))
    case "GET" => FunctionDefinition.standard(2)
    case "GETBIT" => FunctionDefinition.standard(2)
    case "GETDATE" => FunctionDefinition.standard(0)
    case "GETVARIABLE" => FunctionDefinition.standard(1)
    case "GET_ABSOLUTE_PATH" => FunctionDefinition.standard(0)
    case "GET_ANACONDA_PACKAGES_REPODATA" => FunctionDefinition.standard(1)
    case "GET_CONDITION_QUERY_UUID" => FunctionDefinition.standard(0)
    case "GET_DDL" => FunctionDefinition.standard(2, 3)
    case "GET_IGNORE_CASE" => FunctionDefinition.standard(2)
    case "GET_OBJECT_REFERENCES" => FunctionDefinition.standard(3)
    case "GET_PATH" => FunctionDefinition.standard(2)
    case "GET_PRESIGNED_URL" => FunctionDefinition.standard(0)
    case "GET_QUERY_OPERATOR_STATS" => FunctionDefinition.standard(1)
    case "GET_RELATIVE_PATH" => FunctionDefinition.standard(0)
    case "GET_STAGE_LOCATION" => FunctionDefinition.standard(0)
    case "GREATEST" => FunctionDefinition.standard(1, Int.MaxValue)
    case "GREATEST_IGNORE_NULLS" => FunctionDefinition.standard(1)
    case "GROUPING" => FunctionDefinition.standard(1, Int.MaxValue)
    case "GROUPING_ID" => FunctionDefinition.standard(1, Int.MaxValue)
    case "H3_CELL_TO_BOUNDARY" => FunctionDefinition.standard(1)
    case "H3_CELL_TO_CHILDREN" => FunctionDefinition.standard(2)
    case "H3_CELL_TO_CHILDREN_STRING" => FunctionDefinition.standard(2)
    case "H3_CELL_TO_PARENT" => FunctionDefinition.standard(2)
    case "H3_CELL_TO_POINT" => FunctionDefinition.standard(1)
    case "H3_COMPACT_CELLS" => FunctionDefinition.standard(1)
    case "H3_COMPACT_CELLS_STRINGS" => FunctionDefinition.standard(1)
    case "H3_COVERAGE" => FunctionDefinition.standard(2)
    case "H3_COVERAGE_STRINGS" => FunctionDefinition.standard(2)
    case "H3_GET_RESOLUTION" => FunctionDefinition.standard(1)
    case "H3_GRID_DISK" => FunctionDefinition.standard(2)
    case "H3_GRID_DISTANCE" => FunctionDefinition.standard(2)
    case "H3_GRID_PATH" => FunctionDefinition.standard(2)
    case "H3_INT_TO_STRING" => FunctionDefinition.standard(1)
    case "H3_IS_PENTAGON" => FunctionDefinition.standard(1)
    case "H3_IS_VALID_CELL" => FunctionDefinition.standard(1)
    case "H3_LATLNG_TO_CELL" => FunctionDefinition.standard(3)
    case "H3_LATLNG_TO_CELL_STRING" => FunctionDefinition.standard(3)
    case "H3_POINT_TO_CELL" => FunctionDefinition.standard(2)
    case "H3_POINT_TO_CELL_STRING" => FunctionDefinition.standard(2)
    case "H3_POLYGON_TO_CELLS" => FunctionDefinition.standard(2)
    case "H3_POLYGON_TO_CELLS_STRINGS" => FunctionDefinition.standard(2)
    case "H3_STRING_TO_INT" => FunctionDefinition.standard(1)
    case "H3_TRY_COVERAGE" => FunctionDefinition.standard(2)
    case "H3_TRY_COVERAGE_STRINGS" => FunctionDefinition.standard(2)
    case "H3_TRY_GRID_DISTANCE" => FunctionDefinition.standard(2)
    case "H3_TRY_GRID_PATH" => FunctionDefinition.standard(2)
    case "H3_TRY_POLYGON_TO_CELLS" => FunctionDefinition.standard(2)
    case "H3_TRY_POLYGON_TO_CELLS_STRINGS" => FunctionDefinition.standard(2)
    case "H3_UNCOMPACT_CELLS" => FunctionDefinition.standard(2)
    case "H3_UNCOMPACT_CELLS_STRINGS" => FunctionDefinition.standard(2)
    case "HASH" => FunctionDefinition.standard(1, Int.MaxValue)
    case "HASH_AGG" => FunctionDefinition.standard(1, Int.MaxValue)
    case "HAVERSINE" => FunctionDefinition.standard(4)
    case "HEX_DECODE_BINARY" => FunctionDefinition.standard(1)
    case "HEX_DECODE_STRING" => FunctionDefinition.standard(1)
    case "HEX_ENCODE" => FunctionDefinition.standard(1, 2)
    case "HLL" => FunctionDefinition.standard(1, Int.MaxValue)
    case "HLL_ACCUMULATE" => FunctionDefinition.standard(1)
    case "HLL_COMBINE" => FunctionDefinition.standard(1)
    case "HLL_ESTIMATE" => FunctionDefinition.standard(1)
    case "HLL_EXPORT" => FunctionDefinition.standard(1)
    case "HLL_IMPORT" => FunctionDefinition.standard(1)
    case "HOUR / MINUTE / SECOND" => FunctionDefinition.standard(0)
    case "HOUR" => FunctionDefinition.standard(1)
    case "IFF" => FunctionDefinition.standard(3)
    case "IFNULL" => FunctionDefinition.standard(1, 2)
    case "ILIKE ANY" => FunctionDefinition.standard(2, 3)
    case "INFER_SCHEMA" => FunctionDefinition.standard(0)
    case "INITCAP" => FunctionDefinition.standard(1, 2)
    case "INSERT" => FunctionDefinition.standard(4)
    case "INTEGRATION" => FunctionDefinition.standard(1)
    case "INVOKER_ROLE" => FunctionDefinition.standard(0)
    case "INVOKER_SHARE" => FunctionDefinition.standard(0)
    case "IS [ NOT ] DISTINCT FROM" => FunctionDefinition.standard(0)
    case "IS [ NOT ] NULL" => FunctionDefinition.standard(0)
    case "ISNULL" => FunctionDefinition.standard(1)
    case "IS_ARRAY" => FunctionDefinition.standard(1)
    case "IS_BINARY" => FunctionDefinition.standard(1)
    case "IS_BOOLEAN" => FunctionDefinition.standard(1)
    case "IS_CHAR" => FunctionDefinition.standard(1)
    case "IS_DATABASE_ROLE_IN_SESSION" => FunctionDefinition.standard(1)
    case "IS_DATE" => FunctionDefinition.standard(1)
    case "IS_DATE_VALUE" => FunctionDefinition.standard(1)
    case "IS_DECIMAL" => FunctionDefinition.standard(1)
    case "IS_DOUBLE" => FunctionDefinition.standard(1)
    case "IS_GRANTED_TO_INVOKER_ROLE" => FunctionDefinition.standard(1)
    case "IS_INSTANCE_ROLE_IN_SESSION" => FunctionDefinition.standard(1)
    case "IS_INTEGER" => FunctionDefinition.standard(1)
    case "IS_NULL_VALUE" => FunctionDefinition.standard(1)
    case "IS_OBJECT" => FunctionDefinition.standard(1)
    case "IS_REAL" => FunctionDefinition.standard(1)
    case "IS_ROLE_IN_SESSION" => FunctionDefinition.standard(1)
    case "IS_TIME" => FunctionDefinition.standard(1)
    case "IS_TIMESTAMP_LTZ" => FunctionDefinition.standard(1)
    case "IS_TIMESTAMP_NTZ" => FunctionDefinition.standard(1)
    case "IS_TIMESTAMP_TZ" => FunctionDefinition.standard(1)
    case "IS_VARCHAR" => FunctionDefinition.standard(1)
    case "JAROWINKLER_SIMILARITY" => FunctionDefinition.standard(2)
    case "JSON_EXTRACT_PATH_TEXT" => FunctionDefinition.standard(2)
    case "KURTOSIS" => FunctionDefinition.standard(1)
    case "LAG" => FunctionDefinition.standard(1, 3)
    case "LAST_DAY" => FunctionDefinition.standard(1, 2)
    case "LAST_QUERY_ID" => FunctionDefinition.standard(0, 1)
    case "LAST_SUCCESSFUL_SCHEDULED_TIME" => FunctionDefinition.standard(0)
    case "LAST_TRANSACTION" => FunctionDefinition.standard(0)
    case "LAST_VALUE" => FunctionDefinition.standard(1)
    case "LEAD" => FunctionDefinition.standard(1, 3)
    case "LEAST" => FunctionDefinition.standard(1, Int.MaxValue)
    case "LEAST_IGNORE_NULLS" => FunctionDefinition.standard(1)
    case "LEFT" => FunctionDefinition.standard(2)
    case "LEN" => FunctionDefinition.standard(1)
    case "LENGTH" => FunctionDefinition.standard(1)
    case "LIKE ALL" => FunctionDefinition.standard(2, 3)
    case "LIKE ANY" => FunctionDefinition.standard(2, 3)
    case "LISTAGG" => FunctionDefinition.standard(1, 2)
    case "LN" => FunctionDefinition.standard(1)
    case "LOCALTIME" => FunctionDefinition.standard(0)
    case "LOCALTIMESTAMP" => FunctionDefinition.standard(0, 1)
    case "LOG" => FunctionDefinition.standard(2)
    case "LOGIN_HISTORY" =>
      FunctionDefinition.symbolic(Set.empty, Set("TIME_RANGE_START", "TIME_RANGE_END", "RESULT_LIMIT"))
    case "LOGIN_HISTORY_BY_USER" =>
      FunctionDefinition.symbolic(Set.empty, Set("USER_NAME", "TIME_RANGE_START", "TIME_RANGE_END", "RESULT_LIMIT"))
    case "LOWER" => FunctionDefinition.standard(1)
    case "LPAD" => FunctionDefinition.standard(2, 3)
    case "LTRIM" => FunctionDefinition.standard(1, 2)
    case "MAP_CAT" => FunctionDefinition.standard(2)
    case "MAP_CONTAINS_KEY" => FunctionDefinition.standard(2)
    case "MAP_DELETE" => FunctionDefinition.standard(2)
    case "MAP_INSERT" => FunctionDefinition.standard(3, 4)
    case "MAP_KEYS" => FunctionDefinition.standard(1)
    case "MAP_PICK" => FunctionDefinition.standard(4)
    case "MAP_SIZE" => FunctionDefinition.standard(1)
    case "MATERIALIZED_VIEW_REFRESH_HISTORY" =>
      FunctionDefinition.symbolic(Set.empty, Set("DATE_RANGE_START", "DATE_RANGE_END", "MATERIALIZED_VIEW_NAME"))
    case "MAX" => FunctionDefinition.standard(1)
    case "MAX_BY" => FunctionDefinition.standard(2, 3)
    case "MD5" => FunctionDefinition.standard(1)
    case "MD5_BINARY" => FunctionDefinition.standard(1)
    case "MD5_HEX" => FunctionDefinition.standard(1)
    case "MD5_NUMBER — " => FunctionDefinition.standard(1)
    case "MD5_NUMBER_LOWER64" => FunctionDefinition.standard(1)
    case "MD5_NUMBER_UPPER64" => FunctionDefinition.standard(1)
    case "MEDIAN" => FunctionDefinition.standard(1)
    case "MIN (system data metric function)" => FunctionDefinition.standard(1)
    case "MIN" => FunctionDefinition.standard(1)
    case "MINHASH" => FunctionDefinition.standard(2, Int.MaxValue)
    case "MINHASH_COMBINE" => FunctionDefinition.standard(0)
    case "MINUTE" => FunctionDefinition.standard(1)
    case "MIN_BY" => FunctionDefinition.standard(2, 3)
    case "MOD" => FunctionDefinition.standard(2)
    case "MODE" => FunctionDefinition.standard(1)
    case "MONTH" => FunctionDefinition.standard(1)
    case "MONTHNAME" => FunctionDefinition.standard(1)
    case "MONTHS_BETWEEN" => FunctionDefinition.standard(2)
    case "NETWORK_RULE_REFERENCES" => FunctionDefinition.standard(2)
    case "NEXT_DAY" => FunctionDefinition.standard(2)
    case "NORMAL" => FunctionDefinition.standard(3)
    case "NOTIFICATION_HISTORY" => FunctionDefinition.standard(4)
    case "NTH_VALUE" => FunctionDefinition.standard(2)
    case "NTILE" => FunctionDefinition.standard(1)
    case "NULLIF" => FunctionDefinition.standard(2)
    case "NULLIFZERO" => FunctionDefinition.standard(1)
    case "NULL_COUNT (system data metric function)" => FunctionDefinition.standard(1)
    case "NULL_PERCENT (system data metric function)" => FunctionDefinition.standard(1)
    case "NVL" => FunctionDefinition.standard(2).withConversionStrategy(SynonymOf("IFNULL"))
    case "NVL2" => FunctionDefinition.standard(3)
    case "OBJECT_AGG" => FunctionDefinition.standard(2)
    case "OBJECT_CONSTRUCT" => FunctionDefinition.standard(0, Int.MaxValue)
    case "OBJECT_CONSTRUCT_KEEP_NULL" => FunctionDefinition.standard(1, Int.MaxValue)
    case "OBJECT_DELETE" => FunctionDefinition.standard(3)
    case "OBJECT_INSERT" => FunctionDefinition.standard(3, 4)
    case "OBJECT_KEYS" => FunctionDefinition.standard(1)
    case "OBJECT_PICK" => FunctionDefinition.standard(2, Int.MaxValue)
    case "OCTET_LENGTH" => FunctionDefinition.standard(1)
    case "PARSE_IP" => FunctionDefinition.standard(2, 3)
    case "PARSE_JSON" => FunctionDefinition.standard(1)
    case "PARSE_URL" => FunctionDefinition.standard(1, 2)
    case "PARSE_XML" => FunctionDefinition.symbolic(Set("STR"), Set("DISABLE_AUTO_CONVERT"))
    case "PERCENTILE_CONT" => FunctionDefinition.standard(1)
    case "PERCENTILE_DISC" => FunctionDefinition.standard(1)
    case "PERCENT_RANK" => FunctionDefinition.standard(0)
    case "PI" => FunctionDefinition.standard(0)
    case "PIPE_USAGE_HISTORY" =>
      FunctionDefinition.symbolic(Set.empty, Set("DATE_RANGE_START", "DATE_RANGE_END", "PIPE_NAME"))
    case "POLICY_CONTEXT" => FunctionDefinition.standard(7)
    case "POLICY_REFERENCES" =>
      FunctionDefinition.symbolic(Set.empty, Set("POLICY_NAME", "POLICY_KIND", "REF_ENTITY_NAME", "REF_ENTITY_DOMAIN"))
    case "POSITION" => FunctionDefinition.standard(2, 3)
    case "POW" => FunctionDefinition.standard(2)
    case "POWER" => FunctionDefinition.standard(2)
    case "PREVIOUS_DAY" => FunctionDefinition.standard(2)
    case "QUARTER" => FunctionDefinition.standard(1)
    case "QUERY_ACCELERATION_HISTORY" => FunctionDefinition.standard(0)
    case "QUERY_HISTORY" =>
      FunctionDefinition.symbolic(Set.empty, Set("END_TIME_RANGE_START", "END_TIME_RANGE_END", "RESULT_LIMIT"))
    case "QUERY_HISTORY_BY_SESSION" =>
      FunctionDefinition.symbolic(
        Set.empty,
        Set("SESSION_ID", "END_TIME_RANGE_START", "END_TIME_RANGE_END", "RESULT_LIMIT"))
    case "QUERY_HISTORY_BY_USER" =>
      FunctionDefinition.symbolic(
        Set.empty,
        Set("USER_NAME", "END_TIME_RANGE_START", "END_TIME_RANGE_END", "RESULT_LIMIT"))
    case "QUERY_HISTORY_BY_WAREHOUSE" =>
      FunctionDefinition.symbolic(
        Set.empty,
        Set("WAREHOUSE_NAME", "END_TIME_RANGE_START", "END_TIME_RANGE_END", "RESULT_LIMIT"))
    case "RADIANS" => FunctionDefinition.standard(1)
    case "RANDOM" => FunctionDefinition.standard(0, 1)
    case "RANDSTR" => FunctionDefinition.standard(2)
    case "RANK" => FunctionDefinition.standard(0)
    case "RATIO_TO_REPORT" => FunctionDefinition.standard(1)
    case "REGEXP_COUNT" => FunctionDefinition.standard(2, 4)
    case "REGEXP_INSTR" => FunctionDefinition.standard(2, 7)
    case "REGEXP_LIKE" => FunctionDefinition.standard(2, 3)
    case "REGEXP_REPLACE" => FunctionDefinition.standard(2, 6)
    case "REGEXP_SUBSTR" => FunctionDefinition.standard(2, 6)
    case "REGEXP_SUBSTR_ALL" => FunctionDefinition.standard(2, 6)
    case "REGR_AVGX" => FunctionDefinition.standard(2)
    case "REGR_AVGY" => FunctionDefinition.standard(2)
    case "REGR_COUNT" => FunctionDefinition.standard(2)
    case "REGR_INTERCEPT" => FunctionDefinition.standard(2)
    case "REGR_R2" => FunctionDefinition.standard(2)
    case "REGR_SLOPE" => FunctionDefinition.standard(2)
    case "REGR_SXX" => FunctionDefinition.standard(2)
    case "REGR_SXY" => FunctionDefinition.standard(2)
    case "REGR_SYY" => FunctionDefinition.standard(2)
    case "REGR_VALX" => FunctionDefinition.standard(2)
    case "REGR_VALY" => FunctionDefinition.standard(2)
    case "REPEAT" => FunctionDefinition.standard(2)
    case "REPLACE" => FunctionDefinition.standard(2, 3)
    case "REPLICATION_GROUP_REFRESH_HISTORY" => FunctionDefinition.standard(1)
    case "REPLICATION_GROUP_REFRESH_PROGRESS" => FunctionDefinition.standard(1)
    case "REPLICATION_GROUP_REFRESH_PROGRESS_BY_JOB" => FunctionDefinition.standard(1)
    case "REPLICATION_GROUP_USAGE_HISTORY" =>
      FunctionDefinition.symbolic(Set.empty, Set("DATE_RANGE_START", "DATE_RANGE_END", "REPLICATION_GROUP_NAME"))
    case "REPLICATION_USAGE_HISTORY" =>
      FunctionDefinition.symbolic(Set.empty, Set("DATE_RANGE_START", "DATE_RANGE_END", "DATABASE_NAME"))
    case "REST_EVENT_HISTORY" => FunctionDefinition.standard(1, 4)
    case "RESULT_SCAN" => FunctionDefinition.standard(1)
    case "REVERSE" => FunctionDefinition.standard(1)
    case "RIGHT" => FunctionDefinition.standard(2)
    case "RLIKE" => FunctionDefinition.standard(2, 3)
    case "ROUND" => FunctionDefinition.standard(1, 3)
    case "ROW_COUNT (system data metric function)" => FunctionDefinition.standard(0)
    case "ROW_NUMBER" => FunctionDefinition.standard(0)
    case "RPAD" => FunctionDefinition.standard(2, 3)
    case "RTRIM" => FunctionDefinition.standard(1, 2)
    case "RTRIMMED_LENGTH" => FunctionDefinition.standard(1)
    case "SCHEDULED_TIME" => FunctionDefinition.standard(0)
    case "SEARCH_OPTIMIZATION_HISTORY" =>
      FunctionDefinition.symbolic(Set.empty, Set("DATE_RANGE_START", "DATE_RANGE_END", "TABLE_NAME"))
    case "SECOND" => FunctionDefinition.standard(1)
    case "SENTIMENT (SNOWFLAKE.CORTEX)" => FunctionDefinition.standard(1)
    case "SEQ1" => FunctionDefinition.standard(0, 1)
    case "SEQ2" => FunctionDefinition.standard(0, 1)
    case "SEQ4" => FunctionDefinition.standard(0, 1)
    case "SEQ8" => FunctionDefinition.standard(0, 1)
    case "SERVERLESS_TASK_HISTORY" =>
      FunctionDefinition.symbolic(Set.empty, Set("DATE_RANGE_START", "DATE_RANGE_END", "TASK_NAME"))
    case "SHA1" => FunctionDefinition.standard(1)
    case "SHA1_BINARY" => FunctionDefinition.standard(1)
    case "SHA1_HEX" => FunctionDefinition.standard(1)
    case "SHA2" => FunctionDefinition.standard(1, 2)
    case "SHA2_BINARY" => FunctionDefinition.standard(1, 2)
    case "SHA2_HEX" => FunctionDefinition.standard(1, 2)
    case "SHOW_PYTHON_PACKAGES_DEPENDENCIES" => FunctionDefinition.standard(2)
    case "SIGN" => FunctionDefinition.standard(1)
    case "SIN" => FunctionDefinition.standard(1)
    case "SINH" => FunctionDefinition.standard(1)
    case "SKEW" => FunctionDefinition.standard(1)
    case "SOUNDEX" => FunctionDefinition.standard(1)
    case "SOUNDEX_P123" => FunctionDefinition.standard(1)
    case "SPACE" => FunctionDefinition.standard(1)
    case "SPLIT" => FunctionDefinition.standard(2)
    case "SPLIT_PART" => FunctionDefinition.standard(3)
    case "SPLIT_TO_TABLE" => FunctionDefinition.standard(2)
    case "SQRT" => FunctionDefinition.standard(1)
    case "SQUARE" => FunctionDefinition.standard(1)
    case "STAGE_DIRECTORY_FILE_REGISTRATION_HISTORY" => FunctionDefinition.standard(1, 2)
    case "STAGE_STORAGE_USAGE_HISTORY" => FunctionDefinition.standard(2)
    case "STARTSWITH" => FunctionDefinition.standard(2)
    case "STDDEV (system data metric function)" => FunctionDefinition.standard(1)
    case "STDDEV" => FunctionDefinition.standard(1)
    case "STDDEV, STDDEV_SAMP" => FunctionDefinition.standard(3)
    case "STDDEV_POP" => FunctionDefinition.standard(1)
    case "STDDEV_SAMP" => FunctionDefinition.standard(1)
    case "STRIP_NULL_VALUE" => FunctionDefinition.standard(1)
    case "STRTOK" => FunctionDefinition.standard(1, 3)
    case "STRTOK_SPLIT_TO_TABLE" => FunctionDefinition.standard(1, 2)
    case "STRTOK_TO_ARRAY" => FunctionDefinition.standard(1, 2)
    case "ST_AREA" => FunctionDefinition.standard(1)
    case "ST_ASBINARY" => FunctionDefinition.standard(1)
    case "ST_ASEWKB" => FunctionDefinition.standard(1)
    case "ST_ASEWKT" => FunctionDefinition.standard(1)
    case "ST_ASGEOJSON" => FunctionDefinition.standard(1)
    case "ST_ASTEXT" => FunctionDefinition.standard(1)
    case "ST_ASWKB" => FunctionDefinition.standard(1)
    case "ST_ASWKT" => FunctionDefinition.standard(1)
    case "ST_AZIMUTH" => FunctionDefinition.standard(2)
    case "ST_BUFFER" => FunctionDefinition.standard(2)
    case "ST_CENTROID" => FunctionDefinition.standard(1)
    case "ST_COLLECT" => FunctionDefinition.standard(1, 2)
    case "ST_CONTAINS" => FunctionDefinition.standard(2)
    case "ST_COVEREDBY" => FunctionDefinition.standard(2)
    case "ST_COVERS" => FunctionDefinition.standard(2)
    case "ST_DIFFERENCE" => FunctionDefinition.standard(2)
    case "ST_DIMENSION" => FunctionDefinition.standard(1)
    case "ST_DISJOINT" => FunctionDefinition.standard(2)
    case "ST_DISTANCE" => FunctionDefinition.standard(2)
    case "ST_DWITHIN" => FunctionDefinition.standard(3)
    case "ST_ENDPOINT" => FunctionDefinition.standard(1)
    case "ST_ENVELOPE" => FunctionDefinition.standard(1)
    case "ST_GEOGFROMGEOHASH" => FunctionDefinition.standard(1, 2)
    case "ST_GEOGPOINTFROMGEOHASH" => FunctionDefinition.standard(1)
    case "ST_GEOGRAPHYFROMWKB" => FunctionDefinition.standard(1, 2)
    case "ST_GEOGRAPHYFROMWKT" => FunctionDefinition.standard(1, 2)
    case "ST_GEOHASH" => FunctionDefinition.standard(1, 2)
    case "ST_GEOMETRYFROMWKB" => FunctionDefinition.standard(1, 3)
    case "ST_GEOMETRYFROMWKT" => FunctionDefinition.standard(1, 3)
    case "ST_GEOMFROMGEOHASH" => FunctionDefinition.standard(1, 2)
    case "ST_GEOMPOINTFROMGEOHASH" => FunctionDefinition.standard(1)
    case "ST_GEOM_POINT" => FunctionDefinition.standard(2)
    case "ST_HAUSDORFFDISTANCE" => FunctionDefinition.standard(2)
    case "ST_INTERSECTION" => FunctionDefinition.standard(2)
    case "ST_INTERSECTION_AGG" => FunctionDefinition.standard(1)
    case "ST_INTERSECTS" => FunctionDefinition.standard(2)
    case "ST_ISVALID" => FunctionDefinition.standard(1)
    case "ST_LENGTH" => FunctionDefinition.standard(1)
    case "ST_MAKEGEOMPOINT" => FunctionDefinition.standard(2)
    case "ST_MAKELINE" => FunctionDefinition.standard(2)
    case "ST_MAKEPOINT" => FunctionDefinition.standard(2)
    case "ST_MAKEPOLYGON" => FunctionDefinition.standard(1)
    case "ST_MAKEPOLYGONORIENTED" => FunctionDefinition.standard(1)
    case "ST_NPOINTS" => FunctionDefinition.standard(1)
    case "ST_NUMPOINTS" => FunctionDefinition.standard(1)
    case "ST_PERIMETER" => FunctionDefinition.standard(1)
    case "ST_POINT" => FunctionDefinition.standard(2)
    case "ST_POINTN" => FunctionDefinition.standard(2)
    case "ST_POLYGON" => FunctionDefinition.standard(1)
    case "ST_SETSRID" => FunctionDefinition.standard(2)
    case "ST_SIMPLIFY" => FunctionDefinition.standard(2, 3)
    case "ST_SRID" => FunctionDefinition.standard(1)
    case "ST_STARTPOINT" => FunctionDefinition.standard(1)
    case "ST_SYMDIFFERENCE" => FunctionDefinition.standard(2)
    case "ST_TRANSFORM" => FunctionDefinition.standard(2, 3)
    case "ST_UNION" => FunctionDefinition.standard(2)
    case "ST_UNION_AGG" => FunctionDefinition.standard(1)
    case "ST_WITHIN" => FunctionDefinition.standard(2)
    case "ST_X" => FunctionDefinition.standard(1)
    case "ST_XMAX" => FunctionDefinition.standard(1)
    case "ST_XMIN" => FunctionDefinition.standard(1)
    case "ST_Y" => FunctionDefinition.standard(1)
    case "ST_YMAX" => FunctionDefinition.standard(1)
    case "ST_YMIN" => FunctionDefinition.standard(1)
    case "SUBSTR , SUBSTRING" => FunctionDefinition.standard(3)
    case "SUM" => FunctionDefinition.standard(1)
    case "SUMMARIZE (SNOWFLAKE.CORTEX)" => FunctionDefinition.standard(1)
    case "SYSDATE" => FunctionDefinition.standard(0)
    case "SYSTEM$ABORT_SESSION" => FunctionDefinition.standard(1)
    case "SYSTEM$ABORT_TRANSACTION" => FunctionDefinition.standard(1)
    case "SYSTEM$ADD_EVENT (for Snowflake Scripting)" => FunctionDefinition.standard(2)
    case "SYSTEM$ALLOWLIST" => FunctionDefinition.standard(0)
    case "SYSTEM$ALLOWLIST_PRIVATELINK" => FunctionDefinition.standard(0)
    case "SYSTEM$AUTHORIZE_PRIVATELINK" => FunctionDefinition.standard(3)
    case "SYSTEM$AUTHORIZE_STAGE_PRIVATELINK_ACCESS" => FunctionDefinition.standard(1)
    case "SYSTEM$BEHAVIOR_CHANGE_BUNDLE_STATUS" => FunctionDefinition.standard(1)
    case "SYSTEM$BLOCK_INTERNAL_STAGES_PUBLIC_ACCESS" => FunctionDefinition.standard(0)
    case "SYSTEM$CANCEL_ALL_QUERIES" => FunctionDefinition.standard(1)
    case "SYSTEM$CANCEL_QUERY" => FunctionDefinition.standard(1)
    case "SYSTEM$CLEANUP_DATABASE_ROLE_GRANTS" => FunctionDefinition.standard(2)
    case "SYSTEM$CLIENT_VERSION_INFO" => FunctionDefinition.standard(0)
    case "SYSTEM$CLUSTERING_DEPTH" => FunctionDefinition.standard(4)
    case "SYSTEM$CLUSTERING_INFORMATION" => FunctionDefinition.standard(4)
    case "SYSTEM$CLUSTERING_RATIO — " => FunctionDefinition.standard(4)
    case "SYSTEM$CONVERT_PIPES_SQS_TO_SNS" => FunctionDefinition.standard(2)
    case "SYSTEM$CREATE_BILLING_EVENT" => FunctionDefinition.standard(3, 7)
    case "SYSTEM$CURRENT_USER_TASK_NAME" => FunctionDefinition.standard(0)
    case "SYSTEM$DATABASE_REFRESH_HISTORY — " => FunctionDefinition.standard(1)
    case "SYSTEM$DATABASE_REFRESH_PROGRESS , SYSTEM$DATABASE_REFRESH_PROGRESS_BY_JOB — " =>
      FunctionDefinition.standard(2)
    case "SYSTEM$DISABLE_BEHAVIOR_CHANGE_BUNDLE" => FunctionDefinition.standard(1)
    case "SYSTEM$DISABLE_DATABASE_REPLICATION" => FunctionDefinition.standard(1)
    case "SYSTEM$ENABLE_BEHAVIOR_CHANGE_BUNDLE" => FunctionDefinition.standard(1)
    case "SYSTEM$ESTIMATE_AUTOMATIC_CLUSTERING_COSTS" => FunctionDefinition.standard(3)
    case "SYSTEM$ESTIMATE_QUERY_ACCELERATION" => FunctionDefinition.standard(0)
    case "SYSTEM$ESTIMATE_SEARCH_OPTIMIZATION_COSTS" => FunctionDefinition.standard(1, 2)
    case "SYSTEM$EXPLAIN_JSON_TO_TEXT" => FunctionDefinition.standard(1)
    case "SYSTEM$EXPLAIN_PLAN_JSON" => FunctionDefinition.standard(2)
    case "SYSTEM$EXTERNAL_TABLE_PIPE_STATUS" => FunctionDefinition.standard(1)
    case "SYSTEM$FINISH_OAUTH_FLOW" => FunctionDefinition.standard(1)
    case "SYSTEM$GENERATE_SAML_CSR" => FunctionDefinition.standard(2)
    case "SYSTEM$GENERATE_SCIM_ACCESS_TOKEN" => FunctionDefinition.standard(0)
    case "SYSTEM$GET_AWS_SNS_IAM_POLICY" => FunctionDefinition.standard(1)
    case "SYSTEM$GET_CLASSIFICATION_RESULT" => FunctionDefinition.standard(1)
    case "SYSTEM$GET_CMK_AKV_CONSENT_URL" => FunctionDefinition.standard(2)
    case "SYSTEM$GET_CMK_CONFIG" => FunctionDefinition.standard(1)
    case "SYSTEM$GET_CMK_INFO" => FunctionDefinition.standard(0)
    case "SYSTEM$GET_CMK_KMS_KEY_POLICY" => FunctionDefinition.standard(0)
    case "SYSTEM$GET_COMPUTE_POOL_STATUS" => FunctionDefinition.standard(1)
    case "SYSTEM$GET_DIRECTORY_TABLE_STATUS" => FunctionDefinition.standard(0, 1)
    case "SYSTEM$GET_GCP_KMS_CMK_GRANT_ACCESS_CMD" => FunctionDefinition.standard(0)
    case "SYSTEM$GET_ICEBERG_TABLE_INFORMATION" => FunctionDefinition.standard(1)
    case "SYSTEM$GET_LOGIN_FAILURE_DETAILS" => FunctionDefinition.standard(1)
    case "SYSTEM$GET_PREDECESSOR_RETURN_VALUE" => FunctionDefinition.standard(1)
    case "SYSTEM$GET_PRIVATELINK" => FunctionDefinition.standard(3)
    case "SYSTEM$GET_PRIVATELINK_AUTHORIZED_ENDPOINTS" => FunctionDefinition.standard(0)
    case "SYSTEM$GET_PRIVATELINK_CONFIG" => FunctionDefinition.standard(0)
    case "SYSTEM$GET_SERVICE_LOGS" => FunctionDefinition.standard(3, 4)
    case "SYSTEM$GET_SERVICE_STATUS" => FunctionDefinition.standard(1, 2)
    case "SYSTEM$GET_SNOWFLAKE_PLATFORM_INFO" => FunctionDefinition.standard(0)
    case "SYSTEM$GET_TAG" => FunctionDefinition.standard(3)
    case "SYSTEM$GET_TAG_ALLOWED_VALUES" => FunctionDefinition.standard(1)
    case "SYSTEM$GET_TAG_ON_CURRENT_COLUMN" => FunctionDefinition.standard(1)
    case "SYSTEM$GET_TAG_ON_CURRENT_TABLE" => FunctionDefinition.standard(1)
    case "SYSTEM$GET_TASK_GRAPH_CONFIG" => FunctionDefinition.standard(1)
    case "SYSTEM$GLOBAL_ACCOUNT_SET_PARAMETER" => FunctionDefinition.standard(0)
    case "SYSTEM$INTERNAL_STAGES_PUBLIC_ACCESS_STATUS" => FunctionDefinition.standard(0)
    case "SYSTEM$IS_APPLICATION_INSTALLED_FROM_SAME_ACCOUNT" => FunctionDefinition.standard(0)
    case "SYSTEM$IS_APPLICATION_SHARING_EVENTS_WITH_PROVIDER" => FunctionDefinition.standard(0)
    case "SYSTEM$LAST_CHANGE_COMMIT_TIME" => FunctionDefinition.standard(1)
    case "SYSTEM$LINK_ACCOUNT_OBJECTS_BY_NAME" => FunctionDefinition.standard(1)
    case "SYSTEM$LIST_APPLICATION_RESTRICTED_FEATURES" => FunctionDefinition.standard(0)
    case "SYSTEM$LOG, SYSTEM$LOG_<level> (for Snowflake Scripting)" => FunctionDefinition.standard(2)
    case "SYSTEM$MIGRATE_SAML_IDP_REGISTRATION" => FunctionDefinition.standard(2)
    case "SYSTEM$PIPE_FORCE_RESUME" => FunctionDefinition.standard(1)
    case "SYSTEM$PIPE_REBINDING_WITH_NOTIFICATION_CHANNEL" => FunctionDefinition.standard(1)
    case "SYSTEM$PIPE_STATUS" => FunctionDefinition.standard(1)
    case "SYSTEM$QUERY_REFERENCE" => FunctionDefinition.standard(1, 2)
    case "SYSTEM$REFERENCE" => FunctionDefinition.standard(2, 4)
    case "SYSTEM$REGISTER_CMK_INFO" => FunctionDefinition.standard(7)
    case "SYSTEM$REGISTRY_LIST_IMAGES — " => FunctionDefinition.standard(3)
    case "SYSTEM$REVOKE_PRIVATELINK" => FunctionDefinition.standard(3)
    case "SYSTEM$REVOKE_STAGE_PRIVATELINK_ACCESS" => FunctionDefinition.standard(1)
    case "SYSTEM$SET_APPLICATION_RESTRICTED_FEATURE_ACCESS" => FunctionDefinition.standard(0)
    case "SYSTEM$SET_EVENT_SHARING_ACCOUNT_FOR_REGION" => FunctionDefinition.standard(3)
    case "SYSTEM$SET_RETURN_VALUE" => FunctionDefinition.standard(1)
    case "SYSTEM$SET_SPAN_ATTRIBUTES (for Snowflake Scripting)" => FunctionDefinition.standard(1)
    case "SYSTEM$SHOW_ACTIVE_BEHAVIOR_CHANGE_BUNDLES" => FunctionDefinition.standard(0)
    case "SYSTEM$SHOW_BUDGETS_IN_ACCOUNT" => FunctionDefinition.standard(0)
    case "SYSTEM$SHOW_EVENT_SHARING_ACCOUNTS" => FunctionDefinition.standard(0)
    case "SYSTEM$SHOW_OAUTH_CLIENT_SECRETS" => FunctionDefinition.standard(1)
    case "SYSTEM$SNOWPIPE_STREAMING_UPDATE_CHANNEL_OFFSET_TOKEN" => FunctionDefinition.standard(5)
    case "SYSTEM$START_OAUTH_FLOW" => FunctionDefinition.standard(1)
    case "SYSTEM$STREAM_BACKLOG" => FunctionDefinition.standard(1)
    case "SYSTEM$STREAM_GET_TABLE_TIMESTAMP" => FunctionDefinition.standard(1)
    case "SYSTEM$STREAM_HAS_DATA" => FunctionDefinition.standard(1)
    case "SYSTEM$TASK_DEPENDENTS_ENABLE" => FunctionDefinition.standard(1)
    case "SYSTEM$TASK_RUNTIME_INFO" => FunctionDefinition.standard(1)
    case "SYSTEM$TYPEOF" => FunctionDefinition.standard(1)
    case "SYSTEM$UNBLOCK_INTERNAL_STAGES_PUBLIC_ACCESS" => FunctionDefinition.standard(0)
    case "SYSTEM$UNSET_EVENT_SHARING_ACCOUNT_FOR_REGION" => FunctionDefinition.standard(3)
    case "SYSTEM$USER_TASK_CANCEL_ONGOING_EXECUTIONS" => FunctionDefinition.standard(1)
    case "SYSTEM$VALIDATE_STORAGE_INTEGRATION" => FunctionDefinition.standard(4)
    case "SYSTEM$VERIFY_CMK_INFO" => FunctionDefinition.standard(0)
    case "SYSTEM$VERIFY_EXTERNAL_OAUTH_TOKEN" => FunctionDefinition.standard(1)
    case "SYSTEM$WAIT" => FunctionDefinition.standard(1, 2)
    case "SYSTEM$WHITELIST — " => FunctionDefinition.standard(0)
    case "SYSTEM$WHITELIST_PRIVATELINK — " => FunctionDefinition.standard(0)
    case "SYSTIMESTAMP" => FunctionDefinition.standard(0)
    case "TAG_REFERENCES" => FunctionDefinition.standard(2)
    case "TAG_REFERENCES_ALL_COLUMNS" => FunctionDefinition.standard(2)
    case "TAG_REFERENCES_WITH_LINEAGE" => FunctionDefinition.standard(1)
    case "TAN" => FunctionDefinition.standard(1)
    case "TANH" => FunctionDefinition.standard(1)
    case "TASK_DEPENDENTS" => FunctionDefinition.standard(2)
    case "TASK_HISTORY" =>
      FunctionDefinition.symbolic(
        Set.empty,
        Set(
          "SCHEDULED_TIME_RANGE_START",
          "SCHEDULED_TIME_RANGE_END",
          "RESULT_LIMIT",
          "TASK_NAME",
          "ERROR_ONLY",
          "ROOT_TASK_ID"))
    case "TEXT_HTML" => FunctionDefinition.standard(1)
    case "TEXT_PLAIN" => FunctionDefinition.standard(1)
    case "TIME" => FunctionDefinition.standard(1, 2).withConversionStrategy(SynonymOf("TO_TIME"))
    case "TIMEADD" => FunctionDefinition.standard(3).withConversionStrategy(SynonymOf("DATEADD"))
    case "TIMEDIFF" => FunctionDefinition.standard(3)
    case "TIMESTAMPADD" => FunctionDefinition.standard(3)
    case "TIMESTAMPDIFF" => FunctionDefinition.standard(3).withConversionStrategy(SynonymOf("DATEDIFF"))
    case "TIMESTAMP_FROM_PARTS" => FunctionDefinition.standard(2, 8)
    case "TIMESTAMP_LTZ_FROM_PARTS" => FunctionDefinition.standard(6, 7)
    case "TIMESTAMP_NTZ_FROM_PARTS" => FunctionDefinition.standard(2, 7)
    case "TIMESTAMP_TZ_FROM_PARTS" => FunctionDefinition.standard(6, 7)
    case "TIME_FROM_PARTS" => FunctionDefinition.standard(3, 4)
    case "TIME_SLICE" => FunctionDefinition.standard(3, 4)
    case "TOP_INSIGHTS (SNOWFLAKE.ML)" => FunctionDefinition.standard(4)
    case "TO_ARRAY" => FunctionDefinition.standard(1)
    case "TO_BINARY" => FunctionDefinition.standard(1, 2)
    case "TO_BOOLEAN" => FunctionDefinition.standard(1)
    case "TO_CHAR , TO_VARCHAR" => FunctionDefinition.standard(4, 5)
    case "TO_CHAR" => FunctionDefinition.standard(1, 2).withConversionStrategy(SynonymOf("TO_VARCHAR"))
    case "TO_DATE , DATE" => FunctionDefinition.standard(4, 5)
    case "TO_DATE" => FunctionDefinition.standard(1, 2)
    case "TO_DECIMAL" => FunctionDefinition.standard(1, 4).withConversionStrategy(SynonymOf("TO_NUMBER"))
    case "TO_DOUBLE" => FunctionDefinition.standard(1, 2)
    case "TO_GEOGRAPHY" => FunctionDefinition.standard(1, 2)
    case "TO_GEOMETRY" => FunctionDefinition.standard(1, 3)
    case "TO_JSON" => FunctionDefinition.standard(1)
    case "TO_NUMBER" => FunctionDefinition.standard(1, 4)
    case "TO_NUMERIC" => FunctionDefinition.standard(1, 4).withConversionStrategy(SynonymOf("TO_NUMBER"))
    case "TO_OBJECT" => FunctionDefinition.standard(1)
    case "TO_QUERY" => FunctionDefinition.standard(1, 3)
    case "TO_TIME , TIME" => FunctionDefinition.standard(4, 5)
    case "TO_TIME" => FunctionDefinition.standard(1, 2)
    case "TO_TIMESTAMP" => FunctionDefinition.standard(1, 2)
    case "TO_TIMESTAMP_LTZ" => FunctionDefinition.standard(1, 2)
    case "TO_TIMESTAMP_NTZ" => FunctionDefinition.standard(1, 2)
    case "TO_TIMESTAMP_TZ" => FunctionDefinition.standard(1, 2)
    case "TO_VARCHAR" => FunctionDefinition.standard(1, 2)
    case "TO_VARIANT" => FunctionDefinition.standard(1)
    case "TO_XML" => FunctionDefinition.standard(1)
    case "TRANSFORM" => FunctionDefinition.standard(2)
    case "TRANSLATE" => FunctionDefinition.standard(3)
    case "TRIM" => FunctionDefinition.standard(1, 2)
    case "TRUNC" => FunctionDefinition.standard(2)
    case "TRUNCATE" => FunctionDefinition.standard(2)
    case "TRY_BASE64_DECODE_BINARY" => FunctionDefinition.standard(1, 2)
    case "TRY_BASE64_DECODE_STRING" => FunctionDefinition.standard(1, 2)
    case "TRY_CAST" => FunctionDefinition.standard(0)
    case "TRY_COMPLETE (SNOWFLAKE.CORTEX)" => FunctionDefinition.standard(2, 3)
    case "TRY_DECRYPT" => FunctionDefinition.standard(2, 4)
    case "TRY_DECRYPT_RAW" => FunctionDefinition.standard(3, 6)
    case "TRY_HEX_DECODE_BINARY" => FunctionDefinition.standard(1)
    case "TRY_HEX_DECODE_STRING" => FunctionDefinition.standard(1)
    case "TRY_PARSE_JSON" => FunctionDefinition.standard(1)
    case "TRY_TO_BINARY" => FunctionDefinition.standard(1, 2)
    case "TRY_TO_BOOLEAN" => FunctionDefinition.standard(1)
    case "TRY_TO_DATE" => FunctionDefinition.standard(1, 2)
    case "TRY_TO_DECIMAL" => FunctionDefinition.standard(1, 4).withConversionStrategy(SynonymOf("TRY_TO_NUMBER"))
    case "TRY_TO_DOUBLE" => FunctionDefinition.standard(1, 2)
    case "TRY_TO_GEOGRAPHY" => FunctionDefinition.standard(1, 2)
    case "TRY_TO_GEOMETRY" => FunctionDefinition.standard(1, 3)
    case "TRY_TO_NUMBER" => FunctionDefinition.standard(1, 4)
    case "TRY_TO_NUMERIC" => FunctionDefinition.standard(1, 4).withConversionStrategy(SynonymOf("TRY_TO_NUMBER"))
    case "TRY_TO_TIME" => FunctionDefinition.standard(1, 2)
    case "TRY_TO_TIMESTAMP / TRY_TO_TIMESTAMP_*" => FunctionDefinition.standard(2, 3)
    case "TRY_TO_TIMESTAMP" => FunctionDefinition.standard(1, 2)
    case "TRY_TO_TIMESTAMP_LTZ" => FunctionDefinition.standard(1, 2)
    case "TRY_TO_TIMESTAMP_NTZ" => FunctionDefinition.standard(1, 2)
    case "TRY_TO_TIMESTAMP_TZ" => FunctionDefinition.standard(1, 2)
    case "TYPEOF" => FunctionDefinition.standard(1)
    case "UNICODE" => FunctionDefinition.standard(1)
    case "UNIFORM" => FunctionDefinition.standard(3)
    case "UNIQUE_COUNT (system data metric function)" => FunctionDefinition.standard(1)
    case "UPPER" => FunctionDefinition.standard(1)
    case "UUID_STRING" => FunctionDefinition.standard(0, 2)
    case "VALIDATE" => FunctionDefinition.standard(3)
    case "VALIDATE_PIPE_LOAD" => FunctionDefinition.standard(2, 3)
    case "VARIANCE" => FunctionDefinition.standard(1)
    case "VARIANCE_POP" => FunctionDefinition.standard(1)
    case "VARIANCE_SAMP" => FunctionDefinition.standard(1)
    case "VAR_POP" => FunctionDefinition.standard(1)
    case "VAR_SAMP" => FunctionDefinition.standard(1)
    case "VECTOR_COSINE_SIMILARITY" => FunctionDefinition.standard(2)
    case "VECTOR_INNER_PRODUCT" => FunctionDefinition.standard(2)
    case "VECTOR_L2_DISTANCE" => FunctionDefinition.standard(2)
    case "WAREHOUSE_LOAD_HISTORY" =>
      FunctionDefinition.symbolic(Set.empty, Set("DATE_RANGE_START", "DATE_RANGE_END", "WAREHOUSE_NAME"))
    case "WAREHOUSE_METERING_HISTORY" => FunctionDefinition.standard(1, 3)
    case "WEEK" => FunctionDefinition.standard(1)
    case "WEEKISO" => FunctionDefinition.standard(1)
    case "WEEKOFYEAR" => FunctionDefinition.standard(1)
    case "WIDTH_BUCKET" => FunctionDefinition.standard(4)
    case "XMLGET" => FunctionDefinition.standard(2, 3)
    case "YEAR" => FunctionDefinition.standard(1)
    case "YEAROFWEEK" => FunctionDefinition.standard(1)
    case "YEAROFWEEKISO" => FunctionDefinition.standard(1)
    case "ZEROIFNULL" => FunctionDefinition.standard(1)
    case "ZIPF" => FunctionDefinition.standard(3)
    case "[ NOT ] BETWEEN" => FunctionDefinition.standard(0)
    case "[ NOT ] ILIKE" => FunctionDefinition.standard(2, 3)
    case "[ NOT ] IN" => FunctionDefinition.standard(0)
    case "[ NOT ] LIKE" => FunctionDefinition.standard(2, 3)
    case "[ NOT ] REGEXP" => FunctionDefinition.standard(2)
    case "[ NOT ] RLIKE" => FunctionDefinition.standard(2, 3)

  }

  override def functionDefinition(name: String): Option[FunctionDefinition] =
    // If not found, check common functions
    SnowflakeFunctionDefinitionPf.orElse(commonFunctionsPf).lift(name.toUpperCase())

  def applyConversionStrategy(
      functionArity: FunctionDefinition,
      args: Seq[ir.Expression],
      irName: String): ir.Expression = {
    functionArity.conversionStrategy match {
      case Some(strategy) => strategy.convert(irName, args)
      case _ => ir.CallFunction(irName, args)
    }
  }
}

object SnowflakeFunctionConverters {

  case class SynonymOf(canonicalName: String) extends ConversionStrategy {
    override def convert(irName: String, args: Seq[ir.Expression]): ir.Expression = ir.CallFunction(canonicalName, args)
  }

}
