// Copyright 2020 PingCAP, Inc.
//
// 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,
// See the License for the specific language governing permissions and
// limitations under the License.

package configuration

import "strings"

// Hard coded items comes from https://docs.pingcap.com/tidb/stable/dynamic-config

var editableConfigItemsRaw = map[ItemKind]string{
	ItemKindTiKVConfig: `
raftstore.sync-log
raftstore.raft-entry-max-size
raftstore.raft-log-gc-tick-interval
raftstore.raft-log-gc-threshold
raftstore.raft-log-gc-count-limit
raftstore.raft-log-gc-size-limit
raftstore.raft-entry-cache-life-time
raftstore.raft-reject-transfer-leader-duration
raftstore.split-region-check-tick-interval
raftstore.region-split-check-diff
raftstore.region-compact-check-interval
raftstore.region-compact-check-step
raftstore.region-compact-min-tombstones
raftstore.region-compact-tombstones-percent
raftstore.pd-heartbeat-tick-interval
raftstore.pd-store-heartbeat-tick-interval
raftstore.snap-mgr-gc-tick-interval
raftstore.snap-gc-timeout
raftstore.lock-cf-compact-interval
raftstore.lock-cf-compact-bytes-threshold
raftstore.messages-per-tick
raftstore.max-peer-down-duration
raftstore.max-leader-missing-duration
raftstore.abnormal-leader-missing-duration
raftstore.peer-stale-state-check-interval
raftstore.consistency-check-interval
raftstore.raft-store-max-leader-lease
raftstore.allow-remove-leader
raftstore.merge-check-tick-interval
raftstore.cleanup-import-sst-interval
raftstore.local-read-batch-size
raftstore.hibernate-timeout
coprocessor.split-region-on-table
coprocessor.batch-split-limit
coprocessor.region-max-size
coprocessor.region-split-size
coprocessor.region-max-keys
coprocessor.region-split-keys
pessimistic-txn.wait-for-lock-timeout
pessimistic-txn.wake-up-delay-duration
pessimistic-txn.pipelined
gc.ratio-threshold
gc.batch-keys
gc.max-write-bytes-per-sec
gc.enable-compaction-filter
gc.compaction-filter-skip-version-check
raftdb.defaultcf.block-cache-size
raftdb.defaultcf.write-buffer-size
raftdb.defaultcf.max-write-buffer-number
raftdb.defaultcf.max-bytes-for-level-base
raftdb.defaultcf.target-file-size-base
raftdb.defaultcf.level0-file-num-compaction-trigger
raftdb.defaultcf.level0-slowdown-writes-trigger
raftdb.defaultcf.level0-stop-writes-trigger
raftdb.defaultcf.max-compaction-bytes
raftdb.defaultcf.max-bytes-for-level-multiplier
raftdb.defaultcf.disable-auto-compactions
raftdb.defaultcf.soft-pending-compaction-bytes-limit
raftdb.defaultcf.hard-pending-compaction-bytes-limit
raftdb.defaultcf.titan.blob-run-mode
rocksdb.max-total-wal-size
rocksdb.max-background-jobs
rocksdb.max-open-files
rocksdb.compaction-readahead-size
rocksdb.bytes-per-sync
rocksdb.wal-bytes-per-sync
rocksdb.writable-file-max-buffer-size
rocksdb.raftcf.block-cache-size
rocksdb.raftcf.write-buffer-size
rocksdb.raftcf.max-write-buffer-number
rocksdb.raftcf.max-bytes-for-level-base
rocksdb.raftcf.target-file-size-base
rocksdb.raftcf.level0-file-num-compaction-trigger
rocksdb.raftcf.level0-slowdown-writes-trigger
rocksdb.raftcf.level0-stop-writes-trigger
rocksdb.raftcf.max-compaction-bytes
rocksdb.raftcf.max-bytes-for-level-multiplier
rocksdb.raftcf.disable-auto-compactions
rocksdb.raftcf.soft-pending-compaction-bytes-limit
rocksdb.raftcf.hard-pending-compaction-bytes-limit
rocksdb.raftcf.titan.blob-run-mode
rocksdb.defaultcf.block-cache-size
rocksdb.defaultcf.write-buffer-size
rocksdb.defaultcf.max-write-buffer-number
rocksdb.defaultcf.max-bytes-for-level-base
rocksdb.defaultcf.target-file-size-base
rocksdb.defaultcf.level0-file-num-compaction-trigger
rocksdb.defaultcf.level0-slowdown-writes-trigger
rocksdb.defaultcf.level0-stop-writes-trigger
rocksdb.defaultcf.max-compaction-bytes
rocksdb.defaultcf.max-bytes-for-level-multiplier
rocksdb.defaultcf.disable-auto-compactions
rocksdb.defaultcf.soft-pending-compaction-bytes-limit
rocksdb.defaultcf.hard-pending-compaction-bytes-limit
rocksdb.defaultcf.titan.blob-run-mode
rocksdb.lockcf.block-cache-size
rocksdb.lockcf.write-buffer-size
rocksdb.lockcf.max-write-buffer-number
rocksdb.lockcf.max-bytes-for-level-base
rocksdb.lockcf.target-file-size-base
rocksdb.lockcf.level0-file-num-compaction-trigger
rocksdb.lockcf.level0-slowdown-writes-trigger
rocksdb.lockcf.level0-stop-writes-trigger
rocksdb.lockcf.max-compaction-bytes
rocksdb.lockcf.max-bytes-for-level-multiplier
rocksdb.lockcf.disable-auto-compactions
rocksdb.lockcf.soft-pending-compaction-bytes-limit
rocksdb.lockcf.hard-pending-compaction-bytes-limit
rocksdb.lockcf.titan.blob-run-mode
storage.block-cache.capacity
backup.num-threads
split.qps-threshold
split.split-balance-score
split.split-contained-score
`,
	ItemKindPDConfig: `
log.level
cluster-version
schedule.max-merge-region-size
schedule.max-merge-region-keys
schedule.patrol-region-interval
schedule.split-merge-interval
schedule.max-snapshot-count
schedule.max-pending-peer-count
schedule.max-store-down-time
schedule.leader-schedule-policy
schedule.leader-schedule-limit
schedule.region-schedule-limit
schedule.replica-schedule-limit
schedule.merge-schedule-limit
schedule.hot-region-schedule-limit
schedule.hot-region-cache-hits-threshold
schedule.high-space-ratio
schedule.low-space-ratio
schedule.tolerant-size-ratio
schedule.enable-remove-down-replica
schedule.enable-replace-offline-replica
schedule.enable-make-up-replica
schedule.enable-remove-extra-replica
schedule.enable-location-replacement
schedule.enable-cross-table-merge
schedule.enable-one-way-merge
replication.max-replicas
replication.location-labels
replication.enable-placement-rules
replication.strictly-match-label
pd-server.use-region-storage
pd-server.max-gap-reset-ts
pd-server.key-type
pd-server.metric-storage
pd-server.dashboard-address
replication-mode.replication-mode
`,

	// Mark all global variables in TiDB being editable.
	// Due to https://github.com/pingcap/tidb/issues/18517 we have to hard code all global variables for now.
	// TODO: We'd better provide a Editable system variable table as well.
	ItemKindTiDBVariable: `
gtid_mode
flush_time
low_priority_updates
session_track_gtids
ndbinfo_max_rows
ndb_index_stat_option
old_passwords
max_connections
big_tables
slave_pending_jobs_size_max
validate_password_check_user_name
validate_password_number_count
sql_select_limit
ndb_show_foreign_key_mock_tables
default_week_format
binlog_error_action
slave_transaction_retries
default_storage_engine
max_connect_errors
sync_binlog
innodb_fast_shutdown
log_backward_compatible_user_definitions
ft_boolean_syntax
table_definition_cache
sql_mode
server_id
innodb_flushing_avg_loops
tmp_table_size
innodb_max_purge_lag
preload_buffer_size
slave_checkpoint_period
check_proxy_users
innodb_flush_log_at_timeout
innodb_max_undo_log_size
range_alloc_block_size
connect_timeout
max_execution_time
collation_server
innodb_old_blocks_pct
innodb_file_format
innodb_compression_failure_threshold_pct
innodb_checksum_algorithm
relay_log_info_repository
sql_log_bin
super_read_only
max_delayed_threads
new
myisam_sort_buffer_size
optimizer_trace_offset
innodb_buffer_pool_dump_at_shutdown
sql_notes
innodb_cmp_per_index_enabled
innodb_ft_server_stopword_table
binlog_group_commit_sync_delay
binlog_group_commit_sync_no_delay_count
innodb_log_write_ahead_size
general_log
validate_password_dictionary_file
binlog_order_commits
master_verify_checksum
key_cache_division_limit
rpl_semi_sync_master_trace_level
max_insert_delayed_threads
time_zone
innodb_max_dirty_pages_pct
innodb_file_per_table
innodb_log_compressed_pages
master_info_repository
rpl_stop_slave_timeout
innodb_monitor_reset
innodb_print_all_deadlocks
slave_net_timeout
key_buffer_size
foreign_key_checks
host_cache_size
delay_key_write
innodb_file_format_max
debug
log_warnings
offline_mode
innodb_strict_mode
innodb_rollback_segments
join_buffer_size
max_binlog_size
sync_master_info
concurrent_insert
innodb_adaptive_hash_index
innodb_ft_enable_stopword
general_log_file
innodb_support_xa
innodb_compression_level
init_slave
block_encryption_mode
max_length_for_sort_data
interactive_timeout
innodb_optimize_fulltext_only
query_cache_type
query_alloc_block_size
slave_compressed_protocol
init_connect
rpl_semi_sync_slave_trace_level
query_prealloc_size
max_user_connections
innodb_api_trx_level
expire_logs_days
binlog_rows_query_log_events
default_password_lifetime
innodb_status_output_locks
max_error_count
max_write_lock_count
innodb_stats_persistent_sample_pages
show_compatibility_56
log_slow_slave_statements
innodb_spin_wait_delay
thread_cache_size
log_slow_admin_statements
auto_increment_offset
innodb_max_dirty_pages_pct_lwm
log_queries_not_using_indexes
query_cache_wlock_invalidate
sql_buffer_result
character_set_filesystem
collation_database
auto_increment_increment
auto_increment_offset
max_heap_table_size
div_precision_increment
innodb_lru_scan_depth
innodb_purge_rseg_truncate_frequency
sql_auto_is_null
innodb_ft_user_stopword_table
innodb_log_checksum_algorithm
sort_buffer_size
innodb_flush_neighbors
innodb_purge_batch_size
slave_checkpoint_group
character_set_client
innodb_buffer_pool_dump_now
relay_log_purge
ndb_distribution
myisam_data_pointer_size
ndb_optimization_delay
innodb_ft_num_word_optimize
max_join_size
max_seeks_for_key
delayed_insert_timeout
max_relay_log_size
max_sort_length
ndb_eventbuffer_free_percent
binlog_max_flush_queue_time
innodb_fill_factor
log_syslog_facility
transaction_write_set_extraction
ndb_blob_write_batch_bytes
automatic_sp_privileges
innodb_flush_sync
innodb_monitor_disable
slave_parallel_type
innodb_adaptive_flushing_lwm
innodb_buffer_pool_load_now
profiling
sha256_password_proxy_users
sql_quote_show_create
binlogging_impossible_mode
query_cache_size
innodb_stats_transient_sample_pages
innodb_stats_on_metadata
ndb_force_send
log_timestamps
slave_parallel_workers
event_scheduler
ndb_deferred_constraints
log_syslog_include_pid
innodb_disable_sort_file_cache
log_error_verbosity
innodb_replication_delay
slow_query_log
innodb_stats_auto_recalc
lc_messages
bulk_insert_buffer_size
binlog_direct_non_transactional_updates
innodb_change_buffering
sql_big_selects
character_set_results
innodb_max_purge_lag_delay
session_track_schema
innodb_io_capacity_max
innodb_autoextend_increment
binlog_format
optimizer_trace
read_rnd_buffer_size
net_write_timeout
innodb_buffer_pool_load_abort
tx_isolation
transaction_isolation
collation_connection
rpl_semi_sync_master_timeout
transaction_prealloc_size
sync_relay_log
innodb_ft_result_cache_limit
innodb_ft_enable_diag_print
stored_program_cache
innodb_adaptive_max_sleep_delay
session_track_system_variables
innodb_change_buffer_max_size
log_bin_trust_function_creators
mysql_native_password_proxy_users
read_only
innodb_stats_persistent
session_track_state_change
delayed_queue_size
log_syslog
transaction_alloc_block_size
sql_slave_skip_counter
innodb_large_prefix
innodb_io_capacity
max_binlog_cache_size
ndb_index_stat_enable
executed_gtids_compression_period
old_alter_table
long_query_time
log_throttle_queries_not_using_indexes
binlog_cache_size
innodb_compression_pad_pct_max
innodb_commit_concurrency
enforce_gtid_consistency
secure_auth
innodb_random_read_ahead
unique_checks
internal_tmp_disk_storage_engine
myisam_repair_threads
ndb_eventbuffer_max_alloc
innodb_read_ahead_threshold
key_cache_block_size
rpl_semi_sync_slave_enabled
gtid_purged
max_binlog_stmt_cache_size
lock_wait_timeout
read_buffer_size
max_sp_recursion_depth
rpl_semi_sync_master_enabled
slow_query_log_file
innodb_thread_sleep_delay
innodb_ft_aux_table
sql_warnings
keep_files_on_create
slave_preserve_commit_order
slave_exec_mode
binlog_stmt_cache_size
table_open_cache
autocommit
default_tmp_storage_engine
optimizer_search_depth
max_points_in_geometry
innodb_stats_sample_pages
profiling_history_size
character_set_database
storage_engine
sql_log_off
log_syslog_tag
tx_read_only
transaction_read_only
rpl_semi_sync_master_wait_point
innodb_undo_log_truncate
gtid_executed_compression_period
ndb_log_empty_epochs
max_prepared_stmt_count
optimizer_trace_max_mem_size
net_retry_count
optimizer_trace_features
innodb_flush_log_at_trx_commit
rewriter_enabled
query_cache_min_res_unit
updatable_views_with_limit
optimizer_prune_level
slave_sql_verify_checksum
completion_type
binlog_checksum
show_old_temporals
query_cache_limit
innodb_buffer_pool_size
innodb_adaptive_flushing
wait_timeout
innodb_monitor_enable
innodb_buffer_pool_filename
slow_launch_time
slave_max_allowed_packet
ndb_use_transactions
innodb_concurrency_tickets
innodb_monitor_reset_all
ndb_log_updated_only
innodb_old_blocks_time
innodb_stats_method
innodb_lock_wait_timeout
local_infile
myisam_stats_method
innodb_table_locks
net_buffer_length
rpl_semi_sync_master_wait_for_slave_count
binlog_row_image
myisam_max_sort_file_size
rpl_semi_sync_master_wait_no_slave
group_concat_max_len
rewriter_verbose
innodb_undo_logs
delayed_insert_limit
flush
eq_range_index_dive_limit
character_set_connection
myisam_use_mmap
ndb_join_pushdown
character_set_server
validate_password_special_char_count
slave_rows_search_algorithms
ndbinfo_show_hidden
net_read_timeout
max_allowed_packet
sync_relay_log_info
optimizer_trace_limit
validate_password_length
ndb_log_binlog_index
innodb_api_bk_commit_interval
innodb_sync_spin_loops
sql_safe_updates
innodb_thread_concurrency
slave_allow_batching
innodb_buffer_pool_dump_pct
lc_time_names
max_statement_time
end_markers_in_json
avoid_temporal_upgrade
key_cache_age_threshold
innodb_status_output
min_examined_row_limit
sync_frm
innodb_online_alter_log_max_size
information_schema_stats_expiry
thread_pool_size
windowing_use_high_precision
tidb_opt_broadcast_join
tidb_build_stats_concurrency
tidb_auto_analyze_ratio
tidb_auto_analyze_start_time
tidb_auto_analyze_end_time
tidb_executor_concurrency
tidb_distsql_scan_concurrency
tidb_opt_insubq_to_join_and_agg
tidb_opt_correlation_threshold
tidb_opt_correlation_exp_factor
tidb_opt_cpu_factor
tidb_opt_tiflash_concurrency_factor
tidb_opt_copcpu_factor
tidb_opt_network_factor
tidb_opt_scan_factor
tidb_opt_desc_factor
tidb_opt_seek_factor
tidb_opt_memory_factor
tidb_opt_disk_factor
tidb_opt_concurrency_factor
tidb_index_join_batch_size
tidb_index_lookup_size
tidb_index_lookup_concurrency
tidb_index_lookup_join_concurrency
tidb_index_serial_scan_concurrency
tidb_skip_utf8_check
tidb_skip_ascii_check
tidb_max_chunk_size
tidb_allow_batch_cop
tidb_init_chunk_size
tidb_enable_cascades_planner
tidb_enable_index_merge
tidb_enable_table_partition
tidb_hash_join_concurrency
tidb_projection_concurrency
tidb_hashagg_partial_concurrency
tidb_hashagg_final_concurrency
tidb_window_concurrency
tidb_enable_parallel_apply
tidb_backoff_lock_fast
tidb_backoff_weight
tidb_retry_limit
tidb_disable_txn_auto_retry
tidb_constraint_check_in_place
tidb_txn_mode
tidb_row_format_version
tidb_enable_window_function
tidb_enable_vectorized_expression
tidb_enable_fast_analyze
tidb_skip_isolation_level_check
tidb_ddl_reorg_worker_cnt
tidb_ddl_reorg_batch_size
tidb_ddl_error_count_limit
tidb_max_delta_schema_count
tidb_opt_join_reorder_threshold
tidb_scatter_region
tidb_enable_noop_functions
tidb_enable_stmt_summary
tidb_stmt_summary_internal_query
tidb_stmt_summary_refresh_interval
tidb_stmt_summary_history_size
tidb_stmt_summary_max_stmt_count
tidb_stmt_summary_max_sql_length
tidb_capture_plan_baselines
tidb_use_plan_baselines
tidb_evolve_plan_baselines
tidb_evolve_plan_task_max_time
tidb_evolve_plan_task_start_time
tidb_evolve_plan_task_end_time
tidb_store_limit
allow_auto_random_explicit_insert
tidb_enable_clustered_index
tidb_slow_log_masking
tidb_log_desensitization
tidb_shard_allocate_step
tidb_enable_telemetry
`,
}

var editableConfigItems = map[ItemKind]map[string]struct{}{}

func init() {
	for kind, str := range editableConfigItemsRaw {
		editableConfigItems[kind] = make(map[string]struct{})
		configItems := strings.Split(strings.TrimSpace(str), "\n")
		for _, key := range configItems {
			editableConfigItems[kind][key] = struct{}{}
		}
	}
}

func isConfigItemEditable(kind ItemKind, key string) bool {
	if _, ok := editableConfigItems[kind]; !ok {
		return false
	}
	if _, ok := editableConfigItems[kind][key]; !ok {
		return false
	}
	return true
}
