import re

import schema

from clarabot_nano.common.config.utility import writable_directory

LOCAL_CONFIG_SCHEMA = schema.Schema(
    {
        "source": str,  # denormalized absolute path of the file the local config was loaded from
        "log_config": dict,  # no deep checking
        "config_dir": schema.And(str, writable_directory),
        "data_dir": schema.And(str, writable_directory),
        "pid_dir": schema.And(str, len),
        "solr_dir": str,
        "solr_data_dir": schema.And(str, len),
        "solr_logs_dir": schema.And(str, len),
        "solr_heap_size": schema.Regex(r"^\d+[KMG]?$", re.IGNORECASE),
        "tika_dir": str,
        "tika_logs_dir": schema.And(str, len),
        "remote_admin_policy": schema.And(str, lambda s: s in ("allow", "restrict", "deny")),
        "localhost_network_security": schema.And(str, lambda s: s in ("ec", "basic")),
        "path_unicode_normalization": schema.And(str, lambda s: s in ("default", "keep", "NFC", "NFD", "NFKC", "NFKD")),
        "restrict_sensitive_path_access": bool,
        "java_dir": schema.Or(str, None),
        "solr_bundle_dir": schema.Or(str, None),
        "tika_bundle_dir": schema.Or(str, None),
        "tika_heap_size": schema.Regex(r"^\d+[KMG]?$", re.IGNORECASE),
        schema.Optional(object): object,  # allow upgrades to introduce new configuration keys
    }
)
REMOTE_CONFIG_SCHEMA = schema.Schema(
    {
        "name": schema.And(str, lambda s: len(s) < 80),
        "admin_password": schema.Or(str, None),
        "drives": [
            schema.Schema(
                {
                    "path": str,
                    schema.Optional("rooms"): [str],
                    schema.Optional(object): object,  # allow upgrades to introduce new configuration keys
                }
            )
        ],
        "room_blocks": schema.Schema({schema.Optional(str): [str]}),
        "deny_anonymous": bool,
        "indexed_languages": schema.Or(schema.And(str, lambda s: s == "all"), [str]),
        "indexer_sync_interval": schema.And(float, lambda f: f > 0),
        "indexer_remove_lost_count": schema.And(int, lambda i: i > 0),
        "indexer_force_sync_on_startup": bool,
        "indexer_minimum_delay_between_path_sync": schema.And(
            schema.Use(lambda f: min(float(f), 5.0)), lambda f: f >= 0
        ),
        "indexer_reserved_space": schema.And(int, lambda i: i > 0),
        "indexer_ignored_mimes": [str],
        "indexer_extract_size_limit": schema.And(int, lambda i: i >= 1000000),
        "indexer_extract_text_limit": schema.And(int, lambda i: i >= 10000),
        "remote_files_restriction": bool,
        "server_process_number": schema.And(int, lambda i: i > 0),
        "secrets": [bytes],
        schema.Optional(object): object,  # allow upgrades to introduce new configuration keys
    }
)
PARSED_CONFIG_SCHEMA = schema.Schema(
    {
        "local": LOCAL_CONFIG_SCHEMA,
        "remote": REMOTE_CONFIG_SCHEMA,
    }
)
DEFAULT_CONFIG = {
    "local": {
        # deny requests and commands that would change the configuration from remote sources without admin password
        "remote_admin_policy": "restrict",
        # auth & encrypt traffic
        "localhost_network_security": "ec",
        # path access and handling
        "path_unicode_normalization": "default",
        "restrict_sensitive_path_access": True,
        # use bundled dependencies by default
        "java_dir": "",
        "solr_bundle_dir": "",
        "solr_heap_size": "512M",
        "tika_bundle_dir": "",
        "tika_heap_size": "512M",
    },
    "remote": {
        "admin_password": None,
        "drives": [],
        "room_blocks": {},
        "deny_anonymous": False,
        "indexed_languages": [],
        "indexer_sync_interval": 4.0,
        "indexer_remove_lost_count": 3,
        "indexer_force_sync_on_startup": True,
        "indexer_minimum_delay_between_path_sync": 0.0,
        "indexer_reserved_space": 3000,
        "indexer_ignored_mimes": [],
        "indexer_extract_size_limit": 256000000,
        "indexer_extract_text_limit": 1500000,
        "remote_files_restriction": True,
        "server_process_number": 1,
        "secrets": [],
    },
}
