"""
Django settings for gisp project.

Generated by 'django-admin startproject' using Django 1.11.4.

For more information on this file, see
https://docs.djangoproject.com/en/1.11/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.11/ref/settings/
"""
import ast

import logging
import os

import structlog

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
from celery.schedules import crontab

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = ast.literal_eval(os.getenv('GISP_DEBUG', 'False'))

ALLOWED_HOSTS = ast.literal_eval(os.getenv('GISP_ALLOWED_HOSTS', '["*"]'))

# Application definition

INSTALLED_APPS = [
    # Stock Django apps
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.postgres',
    'django.contrib.gis',

    # Third-party apps
    'storages',
    'stdimage',
    'channels',
    'corsheaders',
    'phonenumber_field',
    'waffle',
    'rest_framework',
    'rest_framework.authtoken',
    'rest_framework_gis',
    'redactor',
    'django_filters',
    'cachalot',
    'nested_admin',

    # Our unrelated to the project apps
    'waffle_protected_drf',
    'waffle_featureflags',

    # projects apps
    'pictures',
    'accounts',
    'uploads',
    'regions',
    'organizations'
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',

    'waffle.middleware.WaffleMiddleware',
]

ROOT_URLCONF = 'gisp.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'gisp.wsgi.application'
ASGI_APPLICATION = 'gisp.routing.application'

# Password validation
# https://docs.djangoproject.com/en/1.11/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]

AUTH_USER_MODEL = 'accounts.User'


# Internationalization
# https://docs.djangoproject.com/en/1.11/topics/i18n/

LANGUAGE_CODE = 'ru-RU'

TIME_ZONE = os.getenv('GISP_TIME_ZONE', 'Europe/Moscow')

USE_I18N = True

USE_L10N = True

USE_TZ = True

LOCALE_PATHS = [
    os.path.join(BASE_DIR, 'gisp', 'locale_overridden'),
]

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.11/howto/static-files/

STATICFILES_DIRS = [
    os.path.join(BASE_DIR, "statics"),
]

STATIC_URL = os.getenv('GISP_STATIC_URL', '/static/')
MEDIA_URL = os.getenv('GISP_MEDIA_URL', '/media/')
if DEBUG:
    STATIC_ROOT = os.path.join(BASE_DIR, 'static')
    MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

if 'GISP_SWIFT_AUTH_URL' in os.environ:
    DEFAULT_FILE_STORAGE = 'gisp.storage.SwiftStorage'  # 'swift.storage.SwiftStorage'
    STATICFILES_STORAGE = 'gisp.storage.ManifestStaticSwiftStorage'  # 'swift.storage.StaticSwiftStorage'  # noqa
    SWIFT_AUTH_URL = os.environ['GISP_SWIFT_AUTH_URL']
    SWIFT_USERNAME = os.environ['GISP_SWIFT_USERNAME']
    SWIFT_PASSWORD = os.environ['GISP_SWIFT_PASSWORD']
    SWIFT_CONTAINER_NAME = os.environ['GISP_SWIFT_CONTAINER_NAME']
    SWIFT_STATIC_CONTAINER_NAME = os.environ['GISP_SWIFT_STATIC_CONTAINER_NAME']
    SWIFT_AUTH_TOKEN_DURATION = int(os.getenv('GISP_SWIFT_AUTH_TOKEN_DURATION', 60 * 60 * 23))

    SWIFT_AUTO_BASE_URL = ast.literal_eval(os.getenv('GISP_SWIFT_AUTO_BASE_URL', 'True'))
    if not SWIFT_AUTO_BASE_URL:
        SWIFT_BASE_URL = MEDIA_URL
        SWIFT_STATIC_BASE_URL = STATIC_URL

    # Add prefix to all files. For example, you may put everything
    # to a separate directory of the container.
    SWIFT_NAME_PREFIX = os.getenv('GISP_SWIFT_NAME_PREFIX', '')  # media
    SWIFT_STATIC_NAME_PREFIX = os.getenv('GISP_SWIFT_STATIC_NAME_PREFIX', '')  # static

    # Don't fail everything when manifest file doesn't exist. Our custom extension.
    SWIFT_MANIFEST_STRICT = ast.literal_eval(os.getenv('GISP_SWIFT_MANIFEST_STRICT', 'False'))

FILE_UPLOAD_HANDLERS = [
    'django.core.files.uploadhandler.MemoryFileUploadHandler',
    'django.core.files.uploadhandler.TemporaryFileUploadHandler',
]

# https://github.com/jwilder/nginx-proxy/blob/3ef600a3b56105fa4ac343ef6d10b2c52818fec0/nginx.tmpl#L77
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_SSL', 'on')

# Email

if 'GISP_EMAIL_HOST' in os.environ:
    EMAIL_HOST = os.environ['GISP_EMAIL_HOST']
    EMAIL_HOST_USER = os.environ['GISP_EMAIL_HOST_USER']
    EMAIL_HOST_PASSWORD = os.environ['GISP_EMAIL_HOST_PASSWORD']
    EMAIL_PORT = int(os.getenv('GISP_EMAIL_PORT', None) or 587)
    EMAIL_USE_TLS = True  # STARTTLS, actually

EMAIL_FROM_NOREPLY = os.getenv('GISP_EMAIL_FROM_NOREPLY', None)  # non-Django setting

# Absolute URLs

ABSOLUTE_URI_FRONTEND_URL_PREFIX = os.getenv('GISP_FRONTEND_URL_PREFIX', 'http://localhost:4200/')
ABSOLUTE_URI_API_URL_PREFIX = os.getenv('GISP_API_URL_PREFIX', 'http://localhost:8000/')

# Celery

CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'
CELERY_ACCEPT_CONTENT = ['json']
CELERY_TASK_RESULT_EXPIRES = 12 * 60 * 60  # 12 hours
CELERYD_HIJACK_ROOT_LOGGER = False
CELERYD_REDIRECT_STDOUTS_LEVEL = 'INFO'

CELERY_BEAT_SCHEDULE = {
}

# REST Framework

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    ),

    'DEFAULT_FILTER_BACKENDS': (
        'django_filters.rest_framework.DjangoFilterBackend',
        'rest_framework.filters.SearchFilter',
        'rest_framework.filters.OrderingFilter',
    ),

    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticatedOrReadOnly',
    ],

    'DEFAULT_PAGINATION_CLASS': 'gisp.pagination.PageNumberPaginationWithQueryParams',
    'PAGE_SIZE': 50,

    'DEFAULT_METADATA_CLASS': 'waffle_protected_drf.metadata.WaffleProtectedSimpleMetadata',
    'DEFAULT_CONTENT_NEGOTIATION_CLASS':
        'waffle_protected_drf.negotiation.WaffleContentNegotiation',
    'DEFAULT_RENDERER_CLASSES': (
        'rest_framework.renderers.JSONRenderer',
        'rest_framework.renderers.BrowsableAPIRenderer',
    ),
    'DEFAULT_THROTTLE_RATES': {
        'app_actions': '1/sec',
    }
}

# Statsd (metrics)

STATSD_HOST = os.getenv('GISP_STATSD_HOST', None)
STATSD_PORT = int(os.getenv('GISP_STATSD_PORT', 9125))
PROMETHEUS_NAME_PREFIX = 'GISP_'

# Django channels
CHANNEL_LAYERS = {
    "default": {
        "BACKEND": os.getenv('GISP_CHANNELS_DEFAULT_BACKEND',
                             'channels_redis.core.RedisChannelLayer'),
        "CONFIG": {
            "hosts": [
                os.getenv('GISP_CHANNELS_DEFAULT_CONFIG')
            ]
        },
        "ROUTING": "gisp.routing.channel_routing",
    },
}
# Redactor (Redactor field)
REDACTOR_OPTIONS = {'lang': 'ru'}
# Redactor can upload files to the storage.
# Docs: https://pypi.python.org/pypi/django-wysiwyg-redactor
REDACTOR_UPLOAD = 'redactor/'
REDACTOR_UPLOAD_HANDLER = 'redactor.handlers.UUIDUploader'

# Bleach (HTML sanitizer)
BLEACH_ALLOWED_TAGS = [
    'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'br', 'blockquote', 'pre', 'del',
    'p', 'b', 'i', 'u', 'em', 'strong', 'a', 'figure', 'img', 'ul', 'ol', 'li']
BLEACH_ALLOWED_TAGS_ADMIN = BLEACH_ALLOWED_TAGS + ['iframe']
BLEACH_ALLOWED_ATTRIBUTES = ['href', 'title', 'style', 'alt', 'src', 'data-image', 'data-file']
BLEACH_ALLOWED_STYLES = []
BLEACH_STRIP_COMMENTS = True

# Strip unknown tags if True, replace with HTML escaped characters if
BLEACH_STRIP_TAGS = True
BLEACH_PROTOCOLS = ['http', 'https', 'mailto', 'tel']

# Phone Number
PHONENUMBER_DEFAULT_REGION = 'RU'

# Social Auth
SOCIAL_AUTH_FACEBOOK_SECRET = os.getenv('GISP_SOCIAL_AUTH_FACEBOOK_SECRET', '')
SOCIAL_AUTH_GISP_OAUTH2_SECRET = os.getenv('GISP_SOCIAL_AUTH_GISP_OAUTH2_SECRET', '')

EIS_AUTH_CLIENT_ID = os.getenv('GISP_EIS_AUTH_CLIENT_ID', '')
EIS_AUTH_SECRET = os.getenv('GISP_EIS_AUTH_SECRET', '')

# Logging
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,

    # We use these formatters in our `'handlers'` configration.
    # Probably, you won't need to modify these lines.
    # Unless, you know what you are doing.
    'formatters': {
        'json_formatter': {
            '()': structlog.stdlib.ProcessorFormatter,
            'processor': structlog.processors.JSONRenderer(),
        },
        'console': {
            '()': structlog.stdlib.ProcessorFormatter,
            'processor': structlog.processors.KeyValueRenderer(
                key_order=['timestamp', 'level', 'event', 'logger'],
            ),
        },
    },

    # You can easily swap `key/value` (default) output and `json` ones.
    # Use `'json_console'` if you need `json` logs.
    'handlers': {
        'console': {
            'class': 'logging.StreamHandler',
            'formatter': 'console',
        },
        'json_console': {
            'class': 'logging.StreamHandler',
            'formatter': 'json_formatter',
        },
    },

    # These loggers are required by our app:
    # - django is required when using `logger.getLogger('django')`
    # - security is required by `axes`
    'loggers': {
        'django': {
            'handlers': ['console'],
            'propagate': True,
            'level': 'INFO',
        },
        'security': {
            'handlers': ['console'],
            'level': 'ERROR',
            'propagate': False,
        },
    },
}

structlog.configure(
    processors=[
        structlog.stdlib.filter_by_level,
        structlog.processors.TimeStamper(fmt='iso'),
        structlog.stdlib.add_logger_name,
        structlog.stdlib.add_log_level,
        structlog.stdlib.PositionalArgumentsFormatter(),
        structlog.processors.StackInfoRenderer(),
        structlog.processors.format_exc_info,
        structlog.processors.UnicodeDecoder(),
        structlog.processors.ExceptionPrettyPrinter(),
        structlog.stdlib.ProcessorFormatter.wrap_for_formatter,
    ],
    context_class=structlog.threadlocal.wrap_dict(dict),
    logger_factory=structlog.stdlib.LoggerFactory(),
    wrapper_class=structlog.stdlib.BoundLogger,
    cache_logger_on_first_use=True,
)

# Apps settings

REGIONS_GEOCODER_TIMEOUT = 5
REGIONS_CACHE_TTL_SECONDS = 3600
REGIONS_GEOCODER_FAILURE_BAN_SECONDS = 10 * 60
REGIONS_GOOGLE_API_KEYS = ast.literal_eval(os.getenv('GISP_GOOGLE_MAPS_API_KEYS', '[None]'))

EMAIL_CONFIRMATION_CODE_LENGTH = 100
EMAIL_CONFIRMATION_CODE_DURATION_SECONDS = 3600 * 24 * 5

EMAIL_SIGNALS_ENABLED = ast.literal_eval(os.getenv('GISP_EMAIL_SIGNALS_ENABLED', 'True'))
FEEDBACK_EMAIL_OUR_EMAILS = os.getenv('GISP_FEEDBACK_EMAIL_OUR_EMAILS', '').split(';')

CORS_ORIGIN_WHITELIST = ast.literal_eval(os.getenv('GISP_CORS_ORIGIN_WHITELIST', '[]'))

CORS_ORIGIN_ALLOW_ALL = ast.literal_eval(os.getenv('GISP_CORS_ORIGIN_ALLOW_ALL', 'False'))

if CORS_ORIGIN_WHITELIST:
    CORS_ORIGIN_ALLOW_ALL = False

CORS_ALLOW_HEADERS = [
    'DNT',
    'Keep-Alive',
    'User-Agent',
    'If-Modified-Since',
    'Cache-Control',
    'Content-Type',
    'Authorization',
    'Token'
]

CORS_EXPOSE_HEADERS = CORS_ALLOW_HEADERS

WAFFLE_FEATUREFLAGS_EXPOSE = [
    # (waffle_type, name)
    # Example: `('switch', 'show_ratings'),`
    # Waffle types: https://waffle.readthedocs.io/en/latest/types/index.html
    ('flag', 'contests_enable_flag')
]

EMAILS_CONFIRMATION_CODE_RESEND_DELAY_SECONDS = 60 * 5
EMAILS_SIGNALS_CELERY_TASK_COUNTDOWN = 5

VLR_BACKEND_URL = 'https://api.dobrf.ru/'
VLR_AUTH_BACKEND_URL = 'https://api.staging1.dvl.dobrf.ru'
VLR_NEWS_TAG = 'волонтерыкультуры'

REST_FRAMEWORK_EXTENSIONS = {
    'DEFAULT_CACHE_RESPONSE_TIMEOUT': 60 * 30
}

# EXPERT INVITE
DOMAIN = os.getenv('GISP_DOMAIN', 'localhost:8000')
SEND_EXPERT_INVITE_EMAIL = True

DADATA_TOKEN = os.getenv('GISP_DADATA_TOKEN', '')


def custom_show_toolbar(request):
    """Only show the debug toolbar to users with the superuser flag."""
    return request.user.is_superuser


if DEBUG:
    INSTALLED_APPS += (
        'nplusone.ext.django',
    )

    MIDDLEWARE += (
        'nplusone.ext.django.NPlusOneMiddleware',
    )

    # Logging N+1 requests:
    NPLUSONE_RAISE = False  # comment out if you want to allow N+1 requests
    NPLUSONE_LOGGER = logging.getLogger('django')
    NPLUSONE_LOG_LEVEL = logging.WARN
    NPLUSONE_WHITELIST = [
        {'model': 'admin.*'},
        {'model': 'auth.*'},
        {'model': 'contests.Contest', 'field': 'stages'},
        {'label': 'unused_eager_load', 'model': '*'},
    ]


CACHALOT_ENABLED = True
CACHALOT_CACHE = 'default'
CACHALOT_TIMEOUT = 60*5
CACHALOT_INVALIDATE_RAW = True
CACHALOT_ONLY_CACHABLE_TABLES = (
    'regions_federalsubject',
    'regions_federaldistrict',
)
