# -*- coding: utf-8 -*-

# Copyright 2010 - 2017 RhodeCode GmbH and the AppEnlight project authors
#
# 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,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import hashlib
import os

from pyramid.i18n import TranslationStringFactory
from pyramid import threadlocal

_ = TranslationStringFactory("pyramid")

from appenlight import security
from appenlight.lib import helpers, generate_random_string
from appenlight.models.services.config import ConfigService


def gen_urls(request):
    urls = {
        "baseUrl": request.route_url("/"),
        "applicationsNoId": request.route_url("applications_no_id"),
        "applications": request.route_url(
            "applications", resource_id="REPLACE_ID"
        ).replace("REPLACE_ID", ":resourceId"),
        "applicationsProperty": request.route_url(
            "applications_property", key="REPLACE_KEY", resource_id="REPLACE_ID"
        )
        .replace("REPLACE_ID", ":resourceId")
        .replace("REPLACE_KEY", ":key"),
        "configsNoId": request.route_url("admin_configs"),
        "configs": request.route_url(
            "admin_config", key="REPLACE_KEY", section="REPLACE_SECTION"
        )
        .replace("REPLACE_SECTION", ":section")
        .replace("REPLACE_KEY", ":key"),
        "docs": "http://getappenlight.com/page/api/main.html",
        "eventsNoId": request.route_url("events_no_id"),
        "events": request.route_url("events", event_id="REPLACE_ID").replace(
            "REPLACE_ID", ":eventId"
        ),
        "eventsProperty": request.route_url(
            "events_property", key="REPLACE_KEY", event_id="REPLACE_ID"
        )
        .replace("REPLACE_ID", ":eventId")
        .replace("REPLACE_KEY", ":key"),
        "groupsNoId": request.route_url("groups_no_id"),
        "groups": request.route_url("groups", group_id="REPLACE_ID").replace(
            "REPLACE_ID", ":groupId"
        ),
        "groupsProperty": request.route_url(
            "groups_property", key="REPLACE_KEY", group_id="REPLACE_ID"
        )
        .replace("REPLACE_ID", ":groupId")
        .replace("REPLACE_KEY", ":key"),
        "logsNoId": request.route_url("logs_no_id"),
        "integrationAction": request.route_url(
            "integrations_id",
            action="REPLACE_ACT",
            resource_id="REPLACE_RID",
            integration="REPLACE_IID",
        )
        .replace("REPLACE_RID", ":resourceId")
        .replace("REPLACE_ACT", ":action")
        .replace("REPLACE_IID", ":integration"),
        "usersNoId": request.route_url("users_no_id"),
        "users": request.route_url("users", user_id="REPLACE_ID").replace(
            "REPLACE_ID", ":userId"
        ),
        "usersProperty": request.route_url(
            "users_property", key="REPLACE_KEY", user_id="REPLACE_ID"
        )
        .replace("REPLACE_ID", ":userId")
        .replace("REPLACE_KEY", ":key"),
        "userSelf": request.route_url("users_self"),
        "userSelfProperty": request.route_url(
            "users_self_property", key="REPLACE_KEY"
        ).replace("REPLACE_KEY", ":key"),
        "reports": request.route_url("reports"),
        "reportGroup": request.route_url(
            "report_groups", group_id="REPLACE_RID"
        ).replace("REPLACE_RID", ":groupId"),
        "reportGroupProperty": request.route_url(
            "report_groups_property", key="REPLACE_KEY", group_id="REPLACE_GID"
        )
        .replace("REPLACE_KEY", ":key")
        .replace("REPLACE_GID", ":groupId"),
        "pluginConfigsNoId": request.route_url(
            "plugin_configs", plugin_name="REPLACE_TYPE"
        ).replace("REPLACE_TYPE", ":plugin_name"),
        "pluginConfigs": request.route_url(
            "plugin_config", id="REPLACE_ID", plugin_name="REPLACE_TYPE"
        )
        .replace("REPLACE_ID", ":id")
        .replace("REPLACE_TYPE", ":plugin_name"),
        "resourceProperty": request.route_url(
            "resources_property", key="REPLACE_KEY", resource_id="REPLACE_ID"
        )
        .replace("REPLACE_ID", ":resourceId")
        .replace("REPLACE_KEY", ":key"),
        "slowReports": request.route_url("slow_reports"),
        "sectionView": request.route_url(
            "section_view", section="REPLACE_S", view="REPLACE_V"
        )
        .replace("REPLACE_S", ":section")
        .replace("REPLACE_V", ":view"),
        "otherRoutes": {
            "register": request.route_url("register"),
            "lostPassword": request.route_url("lost_password"),
            "lostPasswordGenerate": request.route_url("lost_password_generate"),
            "signOut": request.route_url("ziggurat.routes.sign_out"),
        },
        "social_auth": {
            "google": request.route_url("social_auth", provider="google"),
            "twitter": request.route_url("social_auth", provider="twitter"),
            "bitbucket": request.route_url("social_auth", provider="bitbucket"),
            "github": request.route_url("social_auth", provider="github"),
        },
        "plugins": {},
        "adminAction": request.route_url("admin", action="REPLACE_ACT").replace(
            "REPLACE_ACT", ":action"
        ),
    }
    return urls


def new_request(event):
    environ = event.request.environ
    event.request.response.headers["X-Frame-Options"] = "SAMEORIGIN"
    event.request.response.headers["X-XSS-Protection"] = "1; mode=block"
    # can this be enabled on non https deployments?
    # event.request.response.headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubdomains;'

    # do not send XSRF token with /api calls
    if not event.request.path.startswith("/api"):
        if environ["wsgi.url_scheme"] == "https":
            event.request.response.set_cookie(
                "XSRF-TOKEN", event.request.session.get_csrf_token(), secure=True
            )
        else:
            event.request.response.set_cookie(
                "XSRF-TOKEN", event.request.session.get_csrf_token()
            )
    if event.request.user:
        event.request.response.headers["x-appenlight-uid"] = (
            "%s" % event.request.user.id
        )


def add_renderer_globals(event):
    request = event.get("request") or threadlocal.get_current_request()

    renderer_globals = event
    renderer_globals["h"] = helpers
    renderer_globals["js_hash"] = request.registry.js_hash
    renderer_globals["css_hash"] = request.registry.css_hash
    renderer_globals["_"] = _
    renderer_globals["security"] = security
    renderer_globals["flash_msgs"] = []
    renderer_globals["appenlight_plugins"] = []

    if "jinja" in event["renderer_info"].type:
        renderer_globals["url_list"] = gen_urls(request)
        # add footer html and some other global vars to renderer
        for module, config in request.registry.appenlight_plugins.items():
            if config["url_gen"]:
                urls = config["url_gen"](request)
                renderer_globals["url_list"]["plugins"][module] = urls

            renderer_globals["appenlight_plugins"].append(
                {
                    "name": module,
                    "config": {
                        "javascript": config["javascript"],
                        "header_html": config["header_html"],
                    },
                }
            )

        footer_config = ConfigService.by_key_and_section(
            "template_footer_html", "global", default_value=""
        )

        renderer_globals["template_footer_html"] = footer_config.value
        try:
            renderer_globals["root_administrator"] = request.has_permission(
                "root_administration", security.RootFactory(request)
            )
        except AttributeError:
            renderer_globals["root_administrator"] = False

    renderer_globals["_mail_url"] = request.registry.settings["_mail_url"]

    if not request:
        return

    # do not sens flash headers with /api calls
    if not request.path.startswith("/api"):
        flash_msgs = helpers.get_type_formatted_flash(request)
        renderer_globals["flash_msgs"] = flash_msgs
        request.add_flash_to_headers()


def application_created(app):
    webassets_dir = app.app.registry.settings.get("webassets.dir")
    js_hash = generate_random_string()
    css_hash = generate_random_string()
    if webassets_dir:
        js_hasher = hashlib.md5()
        css_hasher = hashlib.md5()
        for root, dirs, files in os.walk(webassets_dir):
            for name in files:
                filename = os.path.join(root, name)
                if name.endswith("css"):
                    with open(filename, "r", encoding="utf8", errors="replace") as f:
                        for line in f:
                            css_hasher.update(line.encode("utf8"))
                elif name.endswith("js"):
                    with open(filename, "r", encoding="utf8", errors="replace") as f:
                        for line in f:
                            js_hasher.update(line.encode("utf8"))
        js_hash = js_hasher.hexdigest()
        css_hash = css_hasher.hexdigest()
    app.app.registry.js_hash = js_hash
    app.app.registry.css_hash = css_hash
