#!/usr/bin/python
# -*- coding: utf-8 -*-
#  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.

from datetime import datetime
from github import mstr
from jira_github import Jira
from formatter import Formatter, encode


def daydiff(a, b):
    return (a - b).days


class Report:
    now = datetime.utcnow()
    def __init__(self, header=''):
        self.header = header

    # if padding starts with - it puts padding before contents, otherwise after
    @staticmethod
    def _build_tuple(contents, padding=''):
        if padding is not '':
            out = []
            for i in range(len(contents)):
                out += [padding[1:] + str(contents[i])] if padding[0] is '-' else [str(contents[i]) + padding]
            return tuple(out)
        return contents

    # calls the native print function with the following format. Text1,Text2,... has the correct spacing
    # print ("%s%s%s" % ("Text1, Text2, Text3))
    def print_(self, formatter, row_tuple):
        print (formatter.format % formatter.row_str_format(row_tuple))

class JiraReport(Report):
    def __init__(self, issues, header=''):
        Report.__init__(self, header)
        self.issues = issues

    def view(self, excluded):
        issues_view = dict(self.issues)
        for key in excluded:
            issues_view.pop(key, None)
        return issues_view

    def keys_view(self, excluded):
        return self.view(excluded).keys().sort(Jira.storm_jira_cmp, reverse=True)

    def values_view(self, excluded=None):
        temp_dic = dict(self.issues) if excluded is None else self.view(excluded)
        values = temp_dic.values()
        values.sort(Jira.storm_jira_cmp, reverse=True)
        return values

    @staticmethod
    def _row_tuple(jira):
        return (jira.get_id(), jira.get_trimmed_summary(), daydiff(Report.now, jira.get_created()),
                daydiff(Report.now, jira.get_updated()))

    def _min_width_tuple(self):
        return -1, 43, -1, -1

    def print_report(self):
        print "%s (Count = %s) " % (self.header, len(self.issues))
        jiras = self.values_view()
        fields_tuple = ('Jira Id', 'Summary', 'Created', 'Last Updated (Days)')
        row_tuple = self._row_tuple(jiras[0])

        formatter = Formatter(fields_tuple, row_tuple, self._min_width_tuple())

        self.print_(formatter, fields_tuple)

        for jira in jiras:
            row_tuple = self._row_tuple(jira)
            self.print_(formatter, row_tuple)

    @staticmethod
    def build_jira_url(jira_id):
        BASE_URL = "https://issues.apache.org/jira/browse/"
        return BASE_URL + jira_id


class GitHubReport(Report):
    def __init__(self, pull_requests=None, header=''):
        Report.__init__(self, header)

        if pull_requests is None:
            self.pull_requests = []
            self.type = ''
        else:
            self.pull_requests = pull_requests
            self.type = type

    def _row_tuple(self, pull):
        return self._build_tuple(
            (pull.html_url(), pull.trimmed_title(), daydiff(Report.now, pull.created_at()),
             daydiff(Report.now, pull.updated_at()), pull.user()), '')

    def _min_width_tuple(self):
        return -1, 43, -1, -1, -1

    def print_report(self):
        print "%s (Count = %s) " % (self.header, len(self.pull_requests))

        fields_tuple = self._build_tuple(('URL', 'Title', 'Created', 'Last Updated (Days)', 'User'), '')
        if len(self.pull_requests) > 0:
            row_tuple = self._row_tuple(self.pull_requests[0])

            formatter = Formatter(fields_tuple, row_tuple, self._min_width_tuple())

            self.print_(formatter, fields_tuple)
            for pull in self.pull_requests:
                row_tuple = self._row_tuple(pull)
                self.print_(formatter, row_tuple)

    def jira_ids(self):
        """
        :return: sorted list of JIRA ids present in Git pull requests
        """
        jira_ids = list()
        for pull in self.pull_requests:
            jira_ids.append(pull.jira_id())
        return sorted(jira_ids)

class JiraGitHubCombinedReport(Report):
    def __init__(self, jira_report, github_report, header='', print_comments=False):
        Report.__init__(self, header)
        self.jira_report = jira_report
        self.github_report = github_report
        self.print_comments = print_comments

    def _jira_comments(self, jira_id):
        return None if jira_id is None else self.jira_report.issues[jira_id].get_comments()

    def _idx_1st_comment_with_vote(self):
        g = 0
        for pull in self.github_report.pull_requests:
            c = 0
            for comment in self._jira_comments(pull.jira_id()):
                if comment.has_vote():
                    return(g,) + (c,)
                c += 1
            g += 1

    def _pull_request(self, pull_idx):
        pull = self.github_report.pull_requests[pull_idx]
        return pull

    def _jira_id(self, pull_idx):
        pull = self._pull_request(pull_idx)
        return encode(pull.jira_id())

    def _jira_issue(self, jira_id):
        return self.jira_report.issues[jira_id]

    def _row_tuple(self, pull_idx):
        pull = self._pull_request(pull_idx)
        jira_id = self._jira_id(pull_idx)
        jira_issue = self._jira_issue(jira_id)

        return (jira_id, mstr(pull), jira_issue.get_trimmed_summary(),
                daydiff(Report.now, jira_issue.get_created()),
                daydiff(Report.now, pull.created_at()),
                daydiff(Report.now, jira_issue.get_updated()),
                daydiff(Report.now, pull.updated_at()),
                jira_issue.get_status(), pull.user())

    def _row_tuple_1(self, pull_idx, comment_idx):
        row_tuple_1 = None
        jira_id = self._jira_id(pull_idx)
        jira_comments = self._jira_comments(jira_id)
        comment = jira_comments[comment_idx]
        if comment.has_vote():
            row_tuple_1 = (comment.get_vote(), comment.get_author(), comment.get_pull(),
                           daydiff(Report.now, comment.get_created()))

        return row_tuple_1

    # variables and method names ending with _1 correspond to the comments part
    def print_report(self, print_comments=False):
        print "%s (Count = %s) " % (self.header, len(self.github_report.pull_requests))

        fields_tuple = ('JIRA ID', 'Pull Request', 'Jira Summary', 'JIRA Age',
                        'Pull Age', 'JIRA Update Age', 'Pull Update Age (Days)',
                        'JIRA Status', 'GitHub user')
        row_tuple = self._row_tuple(0)
        formatter = Formatter(fields_tuple, row_tuple)
        self.print_(formatter, fields_tuple)

        row_tuple_1 = ()
        formatter_1 = Formatter()

        if print_comments or self.print_comments:
            fields_tuple_1 = self._build_tuple(('Comment Vote', 'Comment Author', 'Pull URL', 'Comment Age'), '-\t\t')
            row_tuple_1 = self._build_tuple(self._row_tuple_1(*self._idx_1st_comment_with_vote()), '-\t\t')
            formatter_1 = Formatter(fields_tuple_1, row_tuple_1)
            self.print_(formatter_1, fields_tuple_1)
            print ''

        for p in range(0, len(self.github_report.pull_requests)):
            row_tuple = self._row_tuple(p)
            self.print_(formatter, row_tuple)

            if print_comments or self.print_comments:
                has_vote = False
                comments = self._jira_comments(self._jira_id(p))
                for c in range(len(comments)):     # Check cleaner way
                    comment = comments[c]
                    if comment.has_vote():
                        row_tuple_1 = self._build_tuple(self._row_tuple_1(p, c), '-\t\t')
                        if row_tuple_1 is not None:
                            self.print_(formatter_1, row_tuple_1)
                            has_vote = True
                if has_vote:
                    print ''


class CompleteReport(Report):
    def __init__(self, header=''):
        Report.__init__(self, header)
        self.jira_reports = []
        self.github_reports = []
        self.jira_github_combined_reports = []

    def print_all(self):
        if self.header is not '':
            print self.header

        self._print_github_reports()
        self._print_jira_github_combined_reports()
        self._print_jira_reports()

    def _print_jira_reports(self):
        for jira in self.jira_reports:
            jira.print_report()

    def _print_github_reports(self):
        for github in self.github_reports:
            github.print_report()

    def _print_jira_github_combined_reports(self):
        for jira_github_combined in self.jira_github_combined_reports:
            jira_github_combined.print_report()
