# Kanbanara Import Component
# Written by Rebecca Shalfield between 2013 and 2017
# Copyright (c) Rebecca Shalfield 2013-2017
# Released under the GNU AGPL v3

'''Kanbanara's Import Component'''

import csv
import datetime
import logging
import os
import re
import urllib.parse

import cherrypy
from kanbanara import Kanbanara
from pymongo import MongoClient


class Import(Kanbanara):
    '''Kanbanara's Import Component'''

    def __init__(self):
        """Initialisation"""
        self.component = 'import'

        Kanbanara.__init__(self)

        self.current_dir = os.path.dirname(os.path.abspath(__file__))

        logging.basicConfig(level=logging.DEBUG,
                            format='%(asctime)s - %(levelname)s - %(message)s',
                            filename=os.path.join(self.current_dir, '..', 'logs', 'kanbanara.log'),
                            filemode='w'
                           )

        Kanbanara.read_administrator_ini_file(self)

        # Initialisation Settings
        self.mongodb_host, self.mongodb_port, self.mongodb_username, self.mongodb_password, self.mongodb_bindir = Kanbanara.read_mongodb_ini_file(self)

        # Connect to MongoDB on given host and port
        if self.mongodb_username and self.mongodb_password:
            modified_username = urllib.parse.quote_plus(self.mongodb_username)
            modified_password = urllib.parse.quote_plus(self.mongodb_password)
            connection = MongoClient('mongodb://' + modified_username + ':' + modified_password + '@' +
                                     self.mongodb_host + ':' + str(self.mongodb_port))
        else:
            connection = MongoClient(self.mongodb_host, self.mongodb_port)

        # Connect to 'kanbanara' database, creating if not already exists
        kanbanara_db = connection['kanbanara']

        # Connect to 'projects' collection
        self.projects_collection = kanbanara_db['projects']
        for attribute in ['project']:
            self.projects_collection.create_index(attribute, unique=True, background=True)

        # Connect to 'sessions' collection
        self.sessions_collection = kanbanara_db['sessions']
        for attribute in ['session_id']:
            self.sessions_collection.create_index(attribute, unique=True, background=True)

        for attribute in ['lastaccess']:
            self.sessions_collection.create_index(attribute, unique=False, background=True)

        # Connect to 'members' collection
        self.members_collection = kanbanara_db['members']
        for attribute in ['username']:
            # TODO - username attribute should be unique but get error when unique=true set
            self.members_collection.create_index(attribute, unique=False, background=True)

        # Connect to 'cards' collection
        self.cards_collection = kanbanara_db['cards']

    @cherrypy.expose
    def index(self):
        """Redirects you to the kanban board"""
        raise cherrypy.HTTPRedirect("/kanban", 302)

    @cherrypy.expose
    def jira_csv_import(self, adminusername="", adminpassword=""):
        """ Imports a .csv file from JIRA """
        username = Kanbanara.check_authentication(f'/{self.component}/jira_csv_import')
        session_id = Kanbanara.cookie_handling(self)
        session_document = self.sessions_collection.find_one({"session_id": session_id})
        loggedon_member_document = Kanbanara.get_member_document(self, session_document)
        content = []
        content.append(Kanbanara.header(self, "jira_csv_import", "JIRA CSV Import"))
        content.append(Kanbanara.filter_bar(self, 'jira_csv_import'))
        content.append(Kanbanara.menubar(self))
        content.append('<div align="center">')
        content.append(self.insert_page_title_and_online_help(session_document, "jira_csv_import", "JIRA CSV Import"))
        content.append('<p class="warning">Successfully logging into this page will cause a JIRA .csv file to be imported!</p>')
        if adminusername and adminpassword:
            if adminusername == self.kanbanara_settings['admin_username'] and adminpassword == self.kanbanara_settings['admin_password']:
                if os.path.exists(os.path.join(self.current_dir, 'database', 'jira.csv')):
                    csv_reader = csv.reader(open(os.path.join(self.current_dir, 'database', 'jira.csv')), delimiter=',', quotechar='"')
                    project_pos = -1
                    id_pos = -1
                    title_pos = -1
                    type_pos = -1
                    creator_pos = -1
                    priority_pos = -1
                    description_pos = -1
                    owner_pos = -1
                    release_pos = -1
                    state_pos = -1
                    category_pos = -1
                    rows = []
                    for row in csv_reader:
                        rows.append(row)

                    #csv_reader.close()
                    headings = rows[3]
                    active_columns = []
                    for lineNo in range(4, len(rows)):
                        for heading_no, heading in enumerate(headings):
                            if rows[lineNo][heading_no] and heading not in active_columns:
                                active_columns.append(heading)

                    content.append('<p>The following columns are in use:<br><ul>')
                    active_columns.sort()
                    jira_mappings = [('Assignee', 'owner'), ('Description', 'description'), ('Epic Name', 'category'),
                                     ('Issue Type', 'type'), ('Key', 'id'), ('Priority', 'priority'), ('Project', 'project'),
                                     ('Reporter', 'creator'), ('Sprint', 'release'), ('Status', 'state'), ('Summary', 'title')]
                    for activeColumn in active_columns:
                        mapped_onto = ""
                        for (jiraAttribute, kanbanara_attribute) in jira_mappings:
                            if jiraAttribute == activeColumn:
                                mapped_onto = kanbanara_attribute
                                break

                        if mapped_onto:
                            content.append('<li><b>'+activeColumn+'</b> mapped onto <b>'+mapped_onto+'</b></li>')
                        else:
                            content.append('<li><i>'+activeColumn+' is being ignored!</i></li>')

                    content.append('</ul></p>')
                    for col_no, heading in enumerate(headings):
                        if heading == 'Project':
                            project_pos = col_no
                        elif heading == 'Key':
                            id_pos = col_no
                        elif heading == 'Summary':
                            title_pos = col_no
                        elif heading == 'Issue Type':
                            type_pos = col_no
                        elif heading == 'Reporter':
                            creator_pos = col_no
                        elif heading == 'Priority':
                            priority_pos = col_no
                        elif heading == 'Description':
                            description_pos = col_no
                        elif heading == 'Sprint':
                            release_pos = col_no
                        elif heading == 'Assignee':
                            owner_pos = col_no
                        elif heading == 'Status':
                            state_pos = col_no
                        elif heading == 'Epic Name':
                            category_pos = col_no

                    project = ""
                    releases = []
                    members = [loggedon_member_document["username"]]
                    for lineNo in range(4, len(rows)):
                        if project_pos > -1 and rows[lineNo][project_pos]:
                            project = rows[lineNo][project_pos]

                        if owner_pos > -1 and rows[lineNo][owner_pos]:
                            if rows[lineNo][owner_pos] not in members:
                                members.append(rows[lineNo][owner_pos])

                        if release_pos > -1 and rows[lineNo][release_pos]:
                            if rows[lineNo][release_pos] not in releases:
                                releases.append(rows[lineNo][release_pos])

                    if project:
                        project_document = {"project":        project,
                                            "creator":        loggedon_member_document["username"],
                                            "nextcardnumber": 1}
                        releases_list = []
                        if releases:
                            for release in releases:
                                releases_list.append({'release':release})

                            project_document["releases"] = releases_list
                        else:
                            project_document["releases"] = []

                        project_document["members"] = members
                        self.projects_collection.insert(project_document)
                        self.save_project_as_json(project_document)

                    for lineNo in range(4, len(rows)):
                        card_document = {}
                        if project_pos > -1:
                            card_document['project'] = rows[lineNo][project_pos]

                        if id_pos > -1:
                            card_document['id'] = rows[lineNo][id_pos]

                        if title_pos > -1:
                            card_document['title'] = rows[lineNo][title_pos]

                        if owner_pos > -1:
                            card_document['owner'] = rows[lineNo][owner_pos]

                        if type_pos > -1:
                            if rows[lineNo][type_pos] in ['Story']:
                                card_document['type'] = 'story'
                            elif rows[lineNo][type_pos] in ['Improvement']:
                                card_document['type'] = 'enhancement'
                            elif rows[lineNo][type_pos] == 'Technical task':
                                card_document['type'] = 'task'
                            elif rows[lineNo][type_pos] == 'Bug':
                                card_document['type'] = 'defect'
                            elif rows[lineNo][type_pos] == 'Epic':
                                card_document['type'] = 'epic'
                            else:
                                card_document['type'] = rows[lineNo][type_pos]

                        if creator_pos > -1:
                            card_document['creator'] = rows[lineNo][creator_pos]

                        if description_pos > -1:
                            card_document['description'] = rows[lineNo][description_pos]

                        if priority_pos > -1:
                            if rows[lineNo][priority_pos] == 'P1':
                                card_document['priority'] = 'critical'
                            elif rows[lineNo][priority_pos] == 'P2':
                                card_document['priority'] = 'high'
                            elif rows[lineNo][priority_pos] == 'P3':
                                card_document['priority'] = 'medium'
                            elif rows[lineNo][priority_pos] == 'P4':
                                card_document['priority'] = 'low'
                            else:
                                card_document['priority'] = rows[lineNo][priority_pos]

                        if release_pos > -1:
                            card_document['release'] = rows[lineNo][release_pos]

                        if category_pos > -1:
                            card_document['category'] = rows[lineNo][category_pos]

                        if state_pos > -1:
                            if rows[lineNo][state_pos] in ['Closed']:
                                closed_custom_states = self.get_custom_states_mapped_onto_metastates(['closed'])
                                card_document['state'] = closed_custom_states[0]
                            elif rows[lineNo][state_pos] == 'Resolved':
                                accepted_custom_states = self.get_custom_states_mapped_onto_metastates(['acceptancetestingaccepted'])
                                card_document['state'] = accepted_custom_states[0]
                            elif rows[lineNo][state_pos] == 'In Progress':
                                development_custom_states = self.get_custom_states_mapped_onto_metastates(['development'])
                                card_document['state'] = development_custom_states[0]
                            elif rows[lineNo][state_pos] == 'Open':
                                analysis_custom_states = self.get_custom_states_mapped_onto_metastates(['analysis'])
                                card_document['state'] = analysis_custom_states[0]
                            else:
                                card_document['state'] = rows[lineNo][state_pos]

                        if 'project' in card_document and card_document['project']:
                            if 'title' in card_document and card_document['title']:
                                try:
                                    self.cards_collection.insert(card_document)
                                    self.save_card_as_json(card_document)
                                except:
                                    pass

                    if 'projects' in loggedon_member_document:
                        loggedon_member_document['projects'].append(project_document['project'])
                    else:
                        loggedon_member_document['projects'] = [project_document['project']]

                    self.members_collection.save(loggedon_member_document)
                    self.save_member_as_json(loggedon_member_document)

            else:
                raise cherrypy.HTTPError(401, 'Unauthorised')

        else:
            content.append('<form action="/kanban/jira_csv_import" method="post">')
            content.append('<table border="0"><tr><td align="right">Administrator Username</td><td>')
            content.append('<input type="password" size="40" name="adminusername" placeholder="Username">')
            content.append('</td></tr><tr><td align="right">Administrator Password</td><td><input type="password" size="40" name="adminpassword" placeholder="Password"></td></tr><tr><td align="center" colspan="2"><input class="button" type="submit" value="Enter"></td></tr></table></form>')

        content.append('</div>')
        content.append(self.footer())
        return "".join(content)

currentDir = os.path.dirname(os.path.abspath(__file__))
conf = {'/': {'tools.staticdir.root':   currentDir,
              'tools.sessions.on':      True,
              'tools.sessions.locking': 'explicit'
              }}
for directory in ['css', 'images']:
    if os.path.exists(currentDir+os.sep+directory):
        conf['/'+directory] = {'tools.staticdir.on':  True,
                               'tools.staticdir.dir': directory}

cherrypy.tree.mount(Import(), '/import', config=conf)
