# -*- 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 jira
from appenlight.models.integrations import IntegrationBase, IntegrationException

_ = str


class NotFoundException(Exception):
    pass


class JiraIntegration(IntegrationBase):
    __mapper_args__ = {"polymorphic_identity": "jira"}
    front_visible = True
    as_alert_channel = False
    supports_report_alerting = False
    action_notification = True
    integration_action = "Add issue to Jira"


class JiraClient(object):
    def __init__(self, user_name, password, host_name, project, request=None):
        self.user_name = user_name
        self.password = password
        self.host_name = host_name
        self.project = project
        self.request = request
        try:
            self.client = jira.client.JIRA(
                options={"server": host_name}, basic_auth=(user_name, password)
            )
        except jira.JIRAError as e:
            raise IntegrationException(
                "Communication problem: HTTP_STATUS:%s, URL:%s "
                % (e.status_code, e.url)
            )

    def get_projects(self):
        projects = self.client.projects()
        return projects

    def get_assignees(self, request):
        """Gets list of possible assignees"""
        cache_region = request.registry.cache_regions.redis_sec_30

        @cache_region.cache_on_arguments("JiraClient.get_assignees")
        def cached(project_name):
            users = self.client.search_assignable_users_for_issues(
                None, project=project_name
            )
            results = []
            for user in users:
                results.append({"id": user.name, "name": user.displayName})
            return results

        return cached(self.project)

    def get_issue_types(self, request):
        metadata = self.get_metadata(request)
        assignees = self.get_assignees(request)
        parsed_metadata = []
        for entry in metadata["projects"][0]["issuetypes"]:
            issue = {"name": entry["name"], "id": entry["id"], "fields": []}
            for i_id, field_i in entry["fields"].items():
                field = {
                    "name": field_i["name"],
                    "id": i_id,
                    "required": field_i["required"],
                    "values": [],
                    "type": field_i["schema"].get("type"),
                }
                if field_i.get("allowedValues"):
                    field["values"] = []
                    for i in field_i["allowedValues"]:
                        field["values"].append(
                            {"id": i["id"], "name": i.get("name", i.get("value", ""))}
                        )
                if field["id"] == "assignee":
                    field["values"] = assignees
                issue["fields"].append(field)
            parsed_metadata.append(issue)
        return parsed_metadata

    def get_metadata(self, request):
        # cache_region = request.registry.cache_regions.redis_sec_30
        # @cache_region.cache_on_arguments('JiraClient.get_metadata')
        def cached(project_name):
            return self.client.createmeta(
                projectKeys=project_name, expand="projects.issuetypes.fields"
            )

        return cached(self.project)

    def create_issue(self, form_data, request):
        issue_types = self.get_issue_types(request)
        payload = {
            "project": {"key": form_data["project"]},
            "summary": form_data["title"],
            "description": form_data["content"],
            "issuetype": {"id": form_data["issue_type"]},
            "priority": {"id": form_data["priority"]},
            "assignee": {"name": form_data["responsible"]},
        }
        for issue_type in issue_types:
            if issue_type["id"] == form_data["issue_type"]:
                for field in issue_type["fields"]:
                    # set some defaults for other required fields
                    if field == "reporter":
                        payload["reporter"] = {"id": self.user_name}
                    if field["required"] and field["id"] not in payload:
                        if field["type"] == "array":
                            payload[field["id"]] = [field["values"][0]]
                        elif field["type"] == "string":
                            payload[field["id"]] = ""
        new_issue = self.client.create_issue(fields=payload)
        web_url = self.host_name + "/browse/" + new_issue.key
        to_return = {
            "id": new_issue.id,
            "resource_url": new_issue.self,
            "web_url": web_url,
        }
        return to_return
