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

'''Kanbanara's Filters Component'''

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

import cherrypy
from kanbanara import Kanbanara
from pymongo import MongoClient


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

    @cherrypy.expose
    def delete_filter(self, filtername):
        """Allows a saved user-defined filter to be deleted"""
        if filtername:
            session_id = Kanbanara.cookie_handling(self)
            session_document = self.sessions_collection.find_one({"session_id": session_id})
            member_document = Kanbanara.get_member_document(self, session_document)
            filters = member_document.get('filters', [])
            if filters:
                remaining_filters = [filter for filter in filters
                                     if filtername != filter['filtername']]
                if remaining_filters != filters:
                    member_document['filters'] = remaining_filters
                    self.members_collection.save(member_document)
                    self.save_member_as_json(member_document)

        raise cherrypy.HTTPRedirect("/kanban/index", 302)

    @cherrypy.expose
    def filter_manager(self):
        """Allows you to manage your saved filters"""
        page = "filter_manager"
        Kanbanara.check_authentication(f'/{self.component}/'+page)
        session_id = Kanbanara.cookie_handling(self)
        session_document = self.sessions_collection.find_one({"session_id": session_id})
        member_document = Kanbanara.get_member_document(self, session_document)
        content = []
        title = "Filter Manager"
        content.append(Kanbanara.header(self, page, title))
        content.append(Kanbanara.filter_bar(self, page))
        content.append(Kanbanara.menubar(self))
        content.append(self.insert_page_title_and_online_help(session_document, page, title))
        if 'filters' in member_document:
            content.append('<div align="center">')
            filter_settings_and_headings = [('filtername', 'Filter Name'),
                                            ('kanbanboard', 'Kanban Board'),
                                            ('type', 'Type'), ('columns', 'Columns'),
                                            ('teammember', 'Team Member'),
                                            ('project', 'Project'), ('subteam', 'Subteam'),
                                            ('release', 'Release'), ('iteration', 'Iteration'),
                                            ('severity', 'Severity'), ('priority', 'Priority'),
                                            ('card', 'Card'), ('category', 'Category'),
                                            ('hashtag', 'Hashtag'), ('customer', 'Customer'),
                                            ('fontsize', 'Font Size')]
            content.append('<table class="sortable"><thead><tr>')
            for (filter_setting, heading) in filter_settings_and_headings:
                content.append('<th><span>'+heading+'</span></th>')

            content.append('<th></th></tr></thead><tbody>')
            for saved_filter in member_document['filters']:
                content.append('<tr>')
                for (filter_setting, heading) in filter_settings_and_headings:
                    if filter_setting in saved_filter:
                        content.append('<td>'+saved_filter[filter_setting]+'</td>')
                    else:
                        content.append('<td></td>')

                content.append('<td><form action="/filters/delete_filter" method="post">')
                content.append('<input type="hidden" name="filtername" value="'+saved_filter['filtername']+'">')
                content.append('<input type="submit" value="Delete"></form></td></tr>')

            content.append('</tbody></table>')
            content.append('</div>')
            content.append('<script type="text/javascript" src="/scripts/listview.js"></script>')

        content.append(Kanbanara.footer(self))
        return "".join(content)

    @cherrypy.expose
    def reload_filter(self, filter):
        """Allows a filter set previously saved by a user to be reloaded"""
        session_id = Kanbanara.cookie_handling(self)
        session_document = self.sessions_collection.find_one({"session_id": session_id})
        member_document = Kanbanara.get_member_document(self, session_document)
        filters = member_document.get('filters', [])
        for potential_filter in filters:
            if potential_filter['filtername'] == filter:
                for filter_setting in ['filtername', 'card', 'category', 'columns', 'customer',
                                       'fontsize', 'hashtag', 'iteration', 'kanbanboard',
                                       'priority', 'project', 'release', 'severity', 'subteam',
                                       'teammember', 'type']:
                    member_document[filter_setting] = potential_filter.get(filter_setting, '')

                self.members_collection.save(member_document)
                self.save_member_as_json(member_document)

        raise cherrypy.HTTPRedirect("/kanban/index", 302)

    @cherrypy.expose
    def reset_filter(self):
        """Allows the filter bar settings to be reset"""
        username = Kanbanara.check_authentication(f'/{self.component}')
        for member_document in self.members_collection.find({"username": username}):
            for attribute in ["card", "category", "classofservice", "columns", "customer",
                              "fontsize", "hashtag", "iteration", "kanbanboard", "priority",
                              "project", "release", "severity", "subteam", "teammember", "type"]:
                member_document[attribute] = ''

            self.members_collection.save(member_document)
            self.save_member_as_json(member_document)
            break

        raise cherrypy.HTTPRedirect('/kanban', 302)

    @cherrypy.expose
    def save_current_filter(self, filtername=""):
        """Allows the current set of filter settings to be saved under a user-defined name"""
        Kanbanara.check_authentication(f'/{self.component}')
        session_id = Kanbanara.cookie_handling(self)
        session_document = self.sessions_collection.find_one({"session_id": session_id})
        member_document = Kanbanara.get_member_document(self, session_document)
        if filtername:
            filters = member_document.get('filters', [])
            new_filter = {'filtername': filtername}
            for filter_setting in ['card', 'category', 'columns', 'customer', 'fontsize', 'hashtag',
                                   'iteration', 'kanbanboard', 'priority', 'project', 'release',
                                   'severity', 'subteam', 'teammember', 'type']:
                new_filter[filter_setting] = member_document.get(filter_setting, '')

            modified_filters = []
            overwritten = False
            for existing_filter in filters:
                if filtername == existing_filter['filtername']:
                    modified_filters.append(new_filter)
                    overwritten = True
                else:
                    modified_filters.append(existing_filter)

            if not overwritten:
                modified_filters.append(new_filter)

            member_document['filters'] = modified_filters
            self.members_collection.save(member_document)
            self.save_member_as_json(member_document)
            raise cherrypy.HTTPRedirect("/kanban/index", 302)
        else:
            content = []
            content.append(Kanbanara.header(self, 'save_current_filter', 'Save Current Filter'))
            content.append(Kanbanara.filter_bar(self, 'save_current_filter'))
            content.append(Kanbanara.menubar(self))
            content.append(self.insert_page_title_and_online_help(session_document, 'save_current_filter',
                                                                  'Save Current Filter'))
            content.append('<div align="center">')
            content.append('<form action="/filters/save_current_filter" method="post"><table class="form">')
            content.append('<tr><th>Filter Name</th><td>')
            if 'filtername' in member_document and member_document['filtername']:
                content.append('<input type="text" name="filtername" value="'+member_document['filtername']+'">')
            else:
                content.append('<input type="text" name="filtername">')

            content.append('</td></tr>')
            content.append('</tr><td colspan="2"><input type="submit" value="Save Filter"></td></tr>')
            content.append('</table></form>')
            content.append('</div>')
            content.append(Kanbanara.footer(self))
            return "".join(content)

    @cherrypy.expose
    def submit_filter(self, card="", category="", classofservice="", columns="", customer="",
                      destination="", fontsize="", hashtag="", iteration="", kanbanboard="",
                      priority="", project="", release="", severity="", subteam="", swimlanes="",
                      teammember="", card_type=""):
        """Allows the filter bar settings to be saved"""
        Kanbanara.check_authentication(f'/{self.component}')
        session_id = Kanbanara.cookie_handling(self)
        session_document = self.sessions_collection.find_one({"session_id": session_id})
        session_document['lastaccess'] = datetime.datetime.utcnow()
        self.sessions_collection.save(session_document)
        member_document = Kanbanara.get_member_document(self, session_document)
        member_document["card"]           = card
        member_document["category"]       = category
        member_document["classofservice"] = classofservice
        member_document["columns"]        = columns
        member_document["customer"]       = customer
        member_document["fontsize"]       = fontsize
        member_document["hashtag"]        = hashtag
        member_document["iteration"]      = iteration
        member_document["kanbanboard"]    = kanbanboard
        member_document["priority"]       = priority
        member_document["project"]        = project
        member_document["release"]        = release
        member_document["severity"]       = severity
        member_document["subteam"]        = subteam
        member_document["swimlanes"]      = swimlanes
        member_document["teammember"]     = teammember
        member_document["type"]           = card_type
        self.members_collection.save(member_document)
        self.save_member_as_json(member_document)
        raise cherrypy.HTTPRedirect(f'/{self.get_page_component(destination)}/{destination}', 302)

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

        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'
                           )

        # 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 filter_bar_components(self):
        """comment"""
        username = Kanbanara.check_authentication(f'/{self.component}')
        session_id = Kanbanara.cookie_handling(self)
        session_document = self.sessions_collection.find_one({"session_id": session_id})
        member_document = Kanbanara.get_member_document(self, session_document)
        selected_filter_bar_components = member_document.get('filterbarcomponents', {})
        content = []
        content.append(Kanbanara.header(self, 'filter_bar_components', "Filter Bar Components"))
        content.append(Kanbanara.filter_bar(self, 'filter_bar_components'))
        content.append(Kanbanara.menubar(self))
        content.append('<div align="center">')
        content.append(self.insert_page_title_and_online_help(session_document,
                                                              'filter_bar_components', 'Filter Bar Components'))
        content.append('<form action="/filters/update_filter_bar_components" method="post"><table class="form">')
        for filter_bar_component in sorted(self.filter_bar_component_statistics.keys()):
            (heading, status) = self.filter_bar_component_statistics[filter_bar_component]
            if status == 'static':
                content.append('<tr><th>'+heading+'</th><td><span class="fa fa-check fa-lg"></span></td></tr>')
            else:
                if filter_bar_component in selected_filter_bar_components and selected_filter_bar_components[filter_bar_component]:
                    content.append('<tr><th>'+heading+'</th><td><input type="checkbox" name="'+filter_bar_component+'" checked></td></tr>')
                else:
                    content.append('<tr><th>'+heading+'</th><td><input type="checkbox" name="'+filter_bar_component+'"></td></tr>')

        content.append('<tr><td colspan="2"><input type="submit" value="Update"></td></tr></table></form>')
        content.append('</div>')
        content.append(Kanbanara.footer(self))
        return "".join(content)

    @cherrypy.expose
    def update_filter_bar_components(self, card=False, category=False, classofservice=False,
                                     customer=False, fontsize=False, hashtag=False, iteration=False,
                                     priority=False, release=False, severity=False, subteam=False,
                                     swimlanes=False):
        session_id = Kanbanara.cookie_handling(self)
        session_document = self.sessions_collection.find_one({"session_id": session_id})
        member_document = Kanbanara.get_member_document(self, session_document)
        selected_filter_bar_components = {}
        for filter_bar_component in ['kanbanboard', 'classofservice', 'type', 'columns',
                                     'teammember', 'project', 'subteam', 'release', 'iteration',
                                     'severity', 'priority', 'card', 'category', 'hashtag',
                                     'customer', 'fontsize', 'swimlanes']:
            if filter_bar_component in locals() and locals()[filter_bar_component] == 'on':
                selected_filter_bar_components[filter_bar_component] = True
            else:
                selected_filter_bar_components[filter_bar_component] = False

        member_document['filterbarcomponents'] = selected_filter_bar_components
        self.members_collection.save(member_document)
        self.save_member_as_json(member_document)

        raise cherrypy.HTTPRedirect('/kanban', 302)

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

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(Filters(), '/filters', config=conf)
