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

'''Kanbanara's Themes Component'''

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

import cherrypy
from kanbanara import Kanbanara
from pymongo import MongoClient
import scss


class Themes(Kanbanara):
    '''Kanbanara's Themes component'''

    @cherrypy.expose
    def themes(self):
        """Allows a user's theme setting to be updated"""
        Kanbanara.check_authentication(f'/{self.component}/themes')
        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)
        theme = member_document.get('theme', 'kanbanara')
        content = []
        content.append(Kanbanara.header(self, 'themes', 'Themes'))
        content.append(Kanbanara.filter_bar(self, 'themes'))
        content.append(Kanbanara.menubar(self))
        content.append(self.insert_page_title_and_online_help(session_document, 'themes', 'Themes'))
        content.append('<div align="center">')
        content.append('<form action="/themes/update_theme" method="post"><table class="form">')
        content.append('<tr><th>Theme</th><td><select name="theme">')
        potential_themes = os.listdir(os.path.join(self.current_dir, '..', 'css', 'themes'))
        for potential_theme in potential_themes:
            if potential_theme.endswith('.css'):
                potential_theme = potential_theme.replace('.css', '')
                content.append(f'<option value="{potential_theme}"')
                if potential_theme == theme:
                    content.append(' selected')

                content.append(f'>{potential_theme}</option>')

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

    @cherrypy.expose
    def update_theme(self, theme):
        """Updates the user's theme to the selected one, defaulting to kanbanara if empty"""
        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 theme:
            member_document['theme'] = theme
        else:
            member_document['theme'] = 'kanbanara'

        self.members_collection.save(member_document)
        self.save_member_as_json(member_document)
        raise cherrypy.HTTPRedirect("/kanban/index", 302)

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

        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)

    @cherrypy.expose
    def theme_creator(self, acceptancetesting_background="", acceptancetesting_foreground="",
                      acceptancetestingaccepted_background="",
                      acceptancetestingaccepted_foreground="", action="", analysed_background="",
                      analysed_foreground="", analysis_background="", analysis_foreground="",
                      analysispeerreview_background="", analysispeerreview_foreground="",
                      backlog_background="", backlog_foreground="", bug_background="",
                      bug_foreground="", card_background_blocked="", card_foreground_blocked="",
                      card_background_buffered="", card_foreground_buffered="",
                      card_background_closed="", card_foreground_closed="",
                      card_background_deferred="", card_foreground_deferred="",
                      card_background_ghosted="", card_foreground_ghosted="",
                      card_background_waiting="", card_foreground_waiting="", card_id_background="",
                      card_id_foreground="", closed_background="", closed_foreground="",
                      column_background_blocked="", column_foreground_blocked="",
                      column_background_deferred="", column_foreground_deferred="",
                      column_background_ghosted="", column_foreground_ghosted="",
                      column_background_waiting="", column_foreground_waiting="",
                      completed_background="", completed_foreground="", defect_background="",
                      defect_foreground="", defined_background="", defined_foreground="",
                      design_background="", design_foreground="", designpeerreview_background="",
                      designpeerreview_foreground="", designed_background="",
                      designed_foreground="", developed_background="", developed_foreground="",
                      development_background="", development_foreground="",
                      developmentpeerreview_background="", developmentpeerreview_foreground="",
                      enhancement_background="", enhancement_foreground="", epic_background="",
                      epic_foreground="", feature_background="", feature_foreground="",
                      font_family="", integrationtesting_background="",
                      integrationtesting_foreground="", integrationtestingaccepted_background="",
                      integrationtestingaccepted_foreground="", priority_critical_background="",
                      priority_critical_foreground="", priority_high_background="",
                      priority_high_foreground="", priority_low_background="",
                      priority_low_foreground="", priority_medium_background="",
                      priority_medium_foreground="", severity_critical_background="",
                      severity_critical_foreground="", severity_high_background="",
                      severity_high_foreground="", severity_low_background="",
                      severity_low_foreground="", severity_medium_background="",
                      severity_medium_foreground="", story_background="", story_foreground="",
                      systemtesting_background="", systemtesting_foreground="",
                      systemtestingaccepted_background="", systemtestingaccepted_foreground="",
                      task_background="", task_foreground="", test_background="",
                      test_foreground="", themename="", triaged_background="",
                      triaged_foreground="", unittesting_background="", unittesting_foreground="",
                      unittestingaccepted_background="", unittestingaccepted_foreground="",
                      transient_background="", transient_foreground="", untriaged_background="",
                      untriaged_foreground=""):
        '''Allows a theme to be created or updated'''
        Kanbanara.check_authentication(f'/{self.component}/theme_creator')
        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 'theme' in session_document and session_document['theme']:
            theme = session_document['theme']
        else:
            theme = {}

        for (attribute, variable) in [
                ('font_family',                           font_family),
                ('untriaged_foreground',                  untriaged_foreground),
                ('untriaged_background',                  untriaged_background),
                ('triaged_foreground',                    triaged_foreground),
                ('triaged_background',                    triaged_background),
                ('backlog_foreground',                    backlog_foreground),
                ('backlog_background',                    backlog_background),
                ('defined_foreground',                    defined_foreground),
                ('defined_background',                    defined_background),
                ('analysis_foreground',                   analysis_foreground),
                ('analysis_background',                   analysis_background),
                ('analysispeerreview_foreground',         analysispeerreview_foreground),
                ('analysispeerreview_background',         analysispeerreview_background),
                ('analysed_foreground',                   analysed_foreground),
                ('analysed_background',                   analysed_background),
                ('design_foreground',                     design_foreground),
                ('design_background',                     design_background),
                ('designpeerreview_foreground',           designpeerreview_foreground),
                ('designpeerreview_background',           designpeerreview_background),
                ('designed_foreground',                   designed_foreground),
                ('designed_background',                   designed_background),
                ('development_foreground',                development_foreground),
                ('development_background',                development_background),
                ('developmentpeerreview_foreground',      developmentpeerreview_foreground),
                ('developmentpeerreview_background',      developmentpeerreview_background),
                ('developed_foreground',                  developed_foreground),
                ('developed_background',                  developed_background),
                ('unittesting_foreground',                unittesting_foreground),
                ('unittesting_background',                unittesting_background),
                ('unittestingaccepted_foreground',        unittestingaccepted_foreground),
                ('unittestingaccepted_background',        unittestingaccepted_background),
                ('integrationtesting_foreground',         integrationtesting_foreground),
                ('integrationtesting_background',         integrationtesting_background),
                ('integrationtestingaccepted_foreground', integrationtestingaccepted_foreground),
                ('integrationtestingaccepted_background', integrationtestingaccepted_background),
                ('systemtesting_foreground',              systemtesting_foreground),
                ('systemtesting_background',              systemtesting_background),
                ('systemtestingaccepted_foreground',      systemtestingaccepted_foreground),
                ('systemtestingaccepted_background',      systemtestingaccepted_background),
                ('acceptancetesting_foreground',          acceptancetesting_foreground),
                ('acceptancetesting_background',          acceptancetesting_background),
                ('acceptancetestingaccepted_foreground',  acceptancetestingaccepted_foreground),
                ('acceptancetestingaccepted_background',  acceptancetestingaccepted_background),
                ('completed_foreground',                  completed_foreground),
                ('completed_background',                  completed_background),
                ('closed_foreground',                     closed_foreground),
                ('closed_background',                     closed_background),
                ('column_background_blocked',             column_background_blocked),
                ('column_foreground_blocked',             column_foreground_blocked),
                ('column_background_deferred',            column_background_deferred),
                ('column_foreground_deferred',            column_foreground_deferred),
                ('column_background_ghosted',             column_background_ghosted),
                ('column_foreground_ghosted',             column_foreground_ghosted),
                ('column_background_waiting',             column_background_waiting),
                ('column_foreground_waiting',             column_foreground_waiting),
                ('priority_critical_background',          priority_critical_background),
                ('priority_critical_foreground',          priority_critical_foreground),
                ('priority_high_background',              priority_high_background),
                ('priority_high_foreground',              priority_high_foreground),
                ('priority_medium_background',            priority_medium_background),
                ('priority_medium_foreground',            priority_medium_foreground),
                ('priority_low_background',               priority_low_background),
                ('priority_low_foreground',               priority_low_foreground),
                ('severity_critical_background',          severity_critical_background),
                ('severity_critical_foreground',          severity_critical_foreground),
                ('severity_high_background',              severity_high_background),
                ('severity_high_foreground',              severity_high_foreground),
                ('severity_medium_background',            severity_medium_background),
                ('severity_medium_foreground',            severity_medium_foreground),
                ('severity_low_background',               severity_low_background),
                ('severity_low_foreground',               severity_low_foreground),
                ('epic_foreground',                       epic_foreground),
                ('epic_background',                       epic_background),
                ('feature_foreground',                    feature_foreground),
                ('feature_background',                    feature_background),
                ('story_foreground',                      story_foreground),
                ('story_background',                      story_background),
                ('enhancement_foreground',                enhancement_foreground),
                ('enhancement_background',                enhancement_background),
                ('defect_foreground',                     defect_foreground),
                ('defect_background',                     defect_background),
                ('task_foreground',                       task_foreground),
                ('task_background',                       task_background),
                ('test_foreground',                       test_foreground),
                ('test_background',                       test_background),
                ('bug_foreground',                        bug_foreground),
                ('bug_background',                        bug_background),
                ('transient_foreground',                  transient_foreground),
                ('transient_background',                  transient_background),
                ('card_foreground_blocked',               card_foreground_blocked),
                ('card_background_blocked',               card_background_blocked),
                ('card_foreground_buffered',              card_foreground_buffered),
                ('card_background_buffered',              card_background_buffered),
                ('card_foreground_closed',                card_foreground_closed),
                ('card_background_closed',                card_background_closed),
                ('card_foreground_deferred',              card_foreground_deferred),
                ('card_background_deferred',              card_background_deferred),
                ('card_foreground_ghosted',               card_foreground_ghosted),
                ('card_background_ghosted',               card_background_ghosted),
                ('card_foreground_waiting',               card_foreground_waiting),
                ('card_background_waiting',               card_background_waiting),
                ('card_id_foreground',                    card_id_foreground),
                ('card_id_background',                    card_id_background)]:
            if variable or attribute not in theme:
                theme[attribute] = variable
            else:
                variable = theme.get(attribute, '')

        session_document['theme'] = theme
        self.sessions_collection.save(session_document)

        if themename:
            if action == 'Create Theme':
                self.create_theme(themename, theme)
                raise cherrypy.HTTPRedirect("/themes/themes", 302)
            elif action == 'Reload Theme':
                self.reload_theme(session_document, themename)

        content = []
        content.append(Kanbanara.header(self, "theme_creator", "Theme Creator"))
        content.append(Kanbanara.filter_bar(self, 'theme_creator'))
        content.append(Kanbanara.menubar(self))
        content.append('<div align="center">')
        content.append(self.insert_page_title_and_online_help(session_document, 'theme_creator',
                                                              "Theme Creator"))
        content.append('</div>')
        content.append('<form action="/themes/theme_creator" method="post">')

        content.append('<table id="themecreator"><tr><td>') #Container

        content.append('<h3>Font</h3>')
        content.append('<table class="unsortable"><tr><th>Font Family</th></tr>')
        content.append('<tr><td><select name="font_family">')
        content.append('<option value="">Please select...</option>')
        for candidate_font in ['Arial', 'Arial Black', 'Book Antiqua', 'Charcoal', 'Comic Sans MS',
                               'Courier', 'Courier New', 'cursive', 'Gadget', 'Geneva', 'Georgia',
                               'Helvetica', 'Impact', 'Lucida Console', 'Lucida Grande',
                               'Lucida Sans Unicode', 'Monaco', 'monospace', 'Palatino',
                               'Palatino Linotype', 'sans-serif', 'serif', 'Tahoma', 'Times',
                               'Times New Roman', 'Trebuchet MS', 'Verdana']:
            content.append(f'<option style="font-family:{candidate_font}" value="{candidate_font}"')
            if theme['font_family'] and candidate_font == theme['font_family']:
                content.append(' selected')

            content.append(f'>{candidate_font}</option>')

        content.append('</select></td></tr></table>')

        content.append('</td><td>') #Container

        content.append('<h3>Header/Footer</h3>')

        content.append('</td></tr><tr><td>') #Container

        content.append('<h3>Columns/States/Metastates</h3>')
        content.append('<table class="unsortable"><tr><th>Column/State/Metastate</th><th>Background Colour</th><th>Foreground Colour</th></tr>')
        for state in self.metastates_list:
            content.append('<tr><td style="background-color:'+theme[state+'_background']+'; color:'+theme[state+'_foreground']+';">'+state.capitalize()+'</td>')
            for setting in ['background', 'foreground']:
                if theme[state+'_'+setting]:
                    content.append('<td style="background-color:'+theme[state+'_'+setting]+'">')
                else:
                    content.append('<td>')

                content.append('<select name="'+state+'_'+setting+'">')
                content.append('<option value="">Please select...</option>')
                for candidate_colour in self.colours:
                    content.append(f'<option style="background-color:{candidate_colour}" value="{candidate_colour}"')
                    if theme[state+'_'+setting] and candidate_colour == theme[state+'_'+setting]:
                        content.append(' selected')

                    content.append(f'>{candidate_colour}</option>')

                content.append('</select></td>')

            content.append('</tr>')

        content.append('</table>')

        content.append('</td><td>') #Container

        content.append('<h3>Card Types</h3>')
        content.append('<table class="unsortable"><tr><th>Card Type</th><th>Background Colour</th><th>Foreground Colour</th></tr>')
        for card_type in ['epic', 'feature', 'story', 'enhancement', 'defect', 'task', 'test',
                          'bug', 'transient']:
            content.append('<tr><td style="background-color:'+theme[card_type+'_background']+'; color:'+theme[card_type+'_foreground']+';">'+card_type.capitalize()+'</td>')
            for setting in ['background', 'foreground']:
                if theme[card_type+'_'+setting]:
                    content.append('<td style="background-color:'+theme[card_type+'_'+setting]+'">')
                else:
                    content.append('<td>')

                content.append('<select name="'+card_type+'_'+setting+'">')
                content.append('<option value="">Please select...</option>')
                for candidate_colour in self.colours:
                    content.append(f'<option style="background-color:{candidate_colour}" value="{candidate_colour}"')
                    if theme[card_type+'_'+setting] and candidate_colour == theme[card_type+'_'+setting]:
                        content.append(' selected')

                    content.append(f'>{candidate_colour}</option>')

                content.append('</select></td>')

            content.append('</tr>')

        content.append('</table>')

        content.append('</td></tr><tr><td>') #Container

        content.append('<h3>Priorities</h3>')
        content.append('<table class="unsortable"><tr><th>Priority</th><th>Background Colour</th><th>Foreground Colour</th></tr>')
        for priority in self.priorities:
            content.append('<tr><td style="background-color:'+theme['priority_'+priority+'_background']+'; color:'+theme['priority_'+priority+'_foreground']+';">'+priority.capitalize()+'</td>')
            for setting in ['background', 'foreground']:
                if theme['priority_'+priority+'_'+setting]:
                    content.append('<td style="background-color:'+theme['priority_'+priority+'_'+setting]+'">')
                else:
                    content.append('<td>')

                content.append('<select name="priority_'+priority+'_'+setting+'">')
                content.append('<option value="">Please select...</option>')
                for candidate_colour in self.colours:
                    content.append(f'<option style="background-color:{candidate_colour}" value="{candidate_colour}"')
                    if theme['priority_'+priority+'_'+setting] and candidate_colour == theme['priority_'+priority+'_'+setting]:
                        content.append(' selected')

                    content.append('>'+candidate_colour+'</option>')

                content.append('</select></td>')

            content.append('</tr>')

        content.append('</table>')

        content.append('</td><td>') #Container

        content.append('<h3>Severities</h3>')
        content.append('<table class="unsortable"><tr><th>Severity</th><th>Background Colour</th><th>Foreground Colour</th></tr>')
        for severity in self.severities:
            content.append('<tr><td style="background-color:'+theme['severity_'+severity+'_background']+'; color:'+theme['severity_'+severity+'_foreground']+';">'+severity.capitalize()+'</td>')
            for setting in ['background', 'foreground']:
                if theme['severity_'+severity+'_'+setting]:
                    content.append('<td style="background-color:'+theme['severity_'+severity+'_'+setting]+'">')
                else:
                    content.append('<td>')

                content.append('<select name="severity_'+severity+'_'+setting+'">')
                content.append('<option value="">Please select...</option>')
                for candidate_colour in self.colours:
                    content.append(f'<option style="background-color:{candidate_colour}" value="{candidate_colour}"')
                    if theme['severity_'+severity+'_'+setting] and candidate_colour == theme['severity_'+severity+'_'+setting]:
                        content.append(' selected')

                    content.append(f'>{candidate_colour}</option>')

                content.append('</select></td>')

            content.append('</tr>')

        content.append('</table>')

        content.append('</td></tr><tr><td>') #Container

        content.append('<h3>Blocked/Deferred/Ghosted/Waiting Column Sections</h3>')
        content.append('<table class="unsortable"><tr><th>Blocked/Deferred/Ghosted/Waiting</th><th>Background Colour</th><th>Foreground Colour</th></tr>')
        for special in ['blocked', 'deferred', 'ghosted', 'waiting']:
            content.append('<tr><td style="background-color:'+theme['column_background_'+special]+'; color:'+theme['column_foreground_'+special]+';">'+special.capitalize()+'</td>')
            for setting in ['background', 'foreground']:
                if theme['column_'+setting+'_'+special]:
                    content.append('<td style="background-color:'+theme['column_'+setting+'_'+special]+'">')
                else:
                    content.append('<td>')

                content.append('<select name="column_'+setting+'_'+special+'">')
                content.append('<option value="">Please select...</option>')
                for candidate_colour in self.colours:
                    content.append(f'<option style="background-color:{candidate_colour}" value="{candidate_colour}"')
                    if theme['column_'+setting+'_'+special] and candidate_colour == theme['column_'+setting+'_'+special]:
                        content.append(' selected')

                    content.append(f'>{candidate_colour}</option>')

                content.append('</select></td>')

            content.append('</tr>')

        content.append('</table>')

        content.append('</td><td>')

        content.append('<h3>Blocked/Buffered/Closed/Deferred/Ghosted/Waiting Cards</h3>')
        content.append('<table class="unsortable"><tr><th>Blocked/Buffered/Closed/Deferred/Ghosted</th><th>Background Colour</th><th>Foreground Colour</th></tr>')
        for special in ['blocked', 'buffered', 'closed', 'deferred', 'ghosted', 'waiting']:
            content.append('<tr><td style="background-color:'+theme['card_background_'+special]+'; color:'+theme['card_foreground_'+special]+';">'+special.capitalize()+'</td>')
            for setting in ['background', 'foreground']:
                if theme['card_'+setting+'_'+special]:
                    content.append('<td style="background-color:'+theme['card_'+setting+'_'+special]+'">')
                else:
                    content.append('<td>')

                content.append('<select name="card_'+setting+'_'+special+'">')
                content.append('<option value="">Please select...</option>')
                for candidate_colour in self.colours:
                    content.append(f'<option style="background-color:{candidate_colour}" value="{candidate_colour}"')
                    if theme['card_'+setting+'_'+special] and candidate_colour == theme['card_'+setting+'_'+special]:
                        content.append(' selected')

                    content.append(f'>{candidate_colour}</option>')

                content.append('</select></td>')

            content.append('</tr>')

        content.append('</table>')

        content.append('</td></tr><tr><td>') #Container

        content.append('<h3>Card Attributes</h3>')
        content.append('<table class="unsortable"><tr><th>Attribute</th><th>Background Colour</th><th>Foreground Colour</th></tr>')
        for attribute in ['id']:
            content.append('<tr><td style="background-color:'+theme['card_'+attribute+'_background']+'; color:'+theme['card_'+attribute+'_foreground']+';">'+attribute.capitalize()+'</td>')
            for setting in ['background', 'foreground']:
                if theme['card_'+attribute+'_'+setting]:
                    content.append('<td style="background-color:'+theme['card_'+attribute+'_'+setting]+'">')
                else:
                    content.append('<td>')

                content.append('<select name="card_'+attribute+'_'+setting+'">')
                content.append('<option value="">Please select...</option>')
                for candidate_colour in self.colours:
                    content.append(f'<option style="background-color:{candidate_colour}" value="{candidate_colour}"')
                    if theme['card_'+attribute+'_'+setting] and candidate_colour == theme['card_'+attribute+'_'+setting]:
                        content.append(' selected')

                    content.append(f'>{candidate_colour}</option>')

                content.append('</select></td>')

            content.append('</tr>')

        content.append('</table>')

        content.append('</td><td>') #Container

        # TODO - Something to go here

        content.append('</td></tr><tr><td colspan="2">') #Container

        content.append('<p><input type="submit" name="action" value="Save To Session"> ')
        if 'theme' in member_document and member_document['theme']:
            content.append(f'<input type="text" name="themename" value="{member_document["theme"]}">')
        else:
            content.append('<input type="text" name="themename" placeholder="Theme">')

        content.append('<input type="submit" name="action" value="Create Theme"><input type="submit" name="action" value="Reload Theme"></p>')

        content.append('</td></tr></table>') #Container

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

    def reload_theme(self, session_document, themename):
        """Allows the colours within a theme's .scss file to be reloaded into the current session"""
        theme = {}
        theme_scss_file = os.path.join(self.current_dir, '..', 'css', 'themes', themename+'.scss')
        with open(theme_scss_file, "r") as infile:
            theme_scss_code = infile.read()
            for setting in ['font-family']:
                pattern = re.compile(r'\$'+setting.replace('_', '-')+r'\:\s+([\w\- ]+);')
                results = pattern.findall(theme_scss_code)
                if results:
                    theme[setting.replace('-', '_')] = results[0]

            for state in self.metastates_list:
                for setting in ['foreground', 'background']:
                    pattern = re.compile(r'\$'+state+r'\-'+setting+r'\:\s+(\w+);')
                    results = pattern.findall(theme_scss_code)
                    if results:
                        theme[state+'_'+setting] = results[0]

            for priority in ['critical', 'high', 'medium', 'low']:
                for setting in ['background', 'foreground']:
                    pattern = re.compile(r'\$priority\-'+priority+r'\-'+setting+r'\:\s+(\w+);')
                    results = pattern.findall(theme_scss_code)
                    if results:
                        theme['priority'+'_'+priority+'_'+setting] = results[0]

            for severity in ['critical', 'high', 'medium', 'low']:
                for setting in ['background', 'foreground']:
                    pattern = re.compile(r'\$severity\-'+severity+r'\-'+setting+r'\:\s+(\w+);')
                    results = pattern.findall(theme_scss_code)
                    if results:
                        theme['severity'+'_'+severity+'_'+setting] = results[0]

            for special in ['blocked', 'deferred', 'ghosted', 'waiting']:
                for setting in ['background', 'foreground']:
                    pattern = re.compile(r'\$card\-'+setting+r'\-'+special+r'\:\s+(\w+);')
                    results = pattern.findall(theme_scss_code)
                    if results:
                        theme['column'+'_'+setting+'_'+special] = results[0]

            for card_type in ['epic', 'feature', 'story', 'enhancement', 'defect', 'task', 'test',
                              'bug', 'transient']:
                for setting in ['_foreground', '_background', '_foreground_blocked',
                                '_background_blocked']:
                    pattern = re.compile(r'\$'+card_type+setting.replace('_', '-')+r'\:\s+(\w+);')
                    results = pattern.findall(theme_scss_code)
                    if results:
                        theme[card_type+setting] = results[0]

            for special in ['blocked', 'buffered', 'closed', 'deferred', 'ghosted', 'waiting']:
                for setting in ['background', 'foreground']:
                    pattern = re.compile(r'\$card\-'+setting+r'\-'+special+r'\:\s+(\w+);')
                    results = pattern.findall(theme_scss_code)
                    if results:
                        theme['card'+'_'+setting+'_'+special] = results[0]

        session_document['theme'] = theme
        self.sessions_collection.save(session_document)

        raise cherrypy.HTTPRedirect("/themes/theme_creator", 302)

    def create_theme(self, themename, theme):
        '''Allows a theme to be created under the supplied name'''
        if not themename.lower().startswith('kanbanara'):
            kanbanara_scss_path = os.path.join(self.current_dir, '..', 'css',
                                               'themes', 'kanbanara.scss')
            with open(kanbanara_scss_path, "r") as infile:
                theme_scss_code = infile.read()

            for setting in ['font_family']:
                if setting in theme and theme[setting]:
                    pattern = re.compile(r'(\$'+setting.replace('_', '-')+r'\:\s+)([\w\-]+);')
                    results = pattern.findall(theme_scss_code)
                    if results:
                        theme_scss_code = theme_scss_code.replace(results[0][0]+results[0][1],
                                                                  results[0][0]+theme[setting])

            for state in self.metastates_list:
                for setting in ['background', 'foreground']:
                    if state+'_'+setting in theme and theme[state+'_'+setting]:
                        pattern = re.compile(r'(\$'+state+r'\-'+setting+r'\:\s+)(\w+);')
                        results = pattern.findall(theme_scss_code)
                        if results:
                            theme_scss_code = theme_scss_code.replace(results[0][0]+results[0][1],
                                                                      results[0][0]+theme[state+'_'+setting])

            for priority in ['critical', 'high', 'medium', 'low']:
                for setting in ['background', 'foreground']:
                    if 'priority'+'_'+priority+'_'+setting in theme and theme['priority'+'_'+priority+'_'+setting]:
                        pattern = re.compile(r'(\$priority\-'+priority+r'\-'+setting+r'\:\s+)(\w+);')
                        results = pattern.findall(theme_scss_code)
                        if results:
                            theme_scss_code = theme_scss_code.replace(results[0][0]+results[0][1],
                                                                      results[0][0]+theme['priority'+'_'+priority+'_'+setting])

            for severity in ['critical', 'high', 'medium', 'low']:
                for setting in ['background', 'foreground']:
                    if 'severity'+'_'+severity+'_'+setting in theme and theme['severity'+'_'+severity+'_'+setting]:
                        pattern = re.compile(r'(\$severity\-'+severity+r'\-'+setting+r'\:\s+)(\w+);')
                        results = pattern.findall(theme_scss_code)
                        if results:
                            theme_scss_code = theme_scss_code.replace(results[0][0]+results[0][1],
                                                                      results[0][0]+theme['severity'+'_'+severity+'_'+setting])

            for card_type in ['epic', 'feature', 'story', 'enhancement', 'defect', 'task', 'test',
                              'bug', 'transient']:
                for setting in ['_foreground', '_background', '_foreground_blocked',
                                '_background_blocked']:
                    if card_type+setting in theme and theme[card_type+setting]:
                        pattern = re.compile(r'(\$'+card_type+setting.replace('_', '-')+r'\:\s+)(\w+);')
                        results = pattern.findall(theme_scss_code)
                        if results:
                            theme_scss_code = theme_scss_code.replace(results[0][0]+results[0][1],
                                                                      results[0][0]+theme[card_type+setting])

            for special in ['blocked', 'deferred', 'ghosted', 'waiting']:
                for setting in ['background', 'foreground']:
                    if 'column_'+setting+'_'+special in theme and theme['column_'+setting+'_'+special]:
                        pattern = re.compile(r'(\$column\-'+setting+r'\-'+special+r'\:\s+)(\w+);')
                        results = pattern.findall(theme_scss_code)
                        if results:
                            theme_scss_code = theme_scss_code.replace(results[0][0]+results[0][1],
                                                                      results[0][0]+theme['column_'+setting+'_'+special])

            for special in ['blocked', 'buffered', 'deferred', 'closed', 'ghosted', 'waiting']:
                for setting in ['background', 'foreground']:
                    if 'card_'+setting+'_'+special in theme and theme['card_'+setting+'_'+special]:
                        pattern = re.compile(r'(\$card\-'+setting+r'\-'+special+r'\:\s+)(\w+);')
                        results = pattern.findall(theme_scss_code)
                        if results:
                            theme_scss_code = theme_scss_code.replace(results[0][0]+results[0][1],
                                                                      results[0][0]+theme['card_'+setting+'_'+special])

            for attribute in ['id']:
                for setting in ['_foreground', '_background']:
                    if 'card_'+attribute+setting in theme and theme['card_'+attribute+setting]:
                        theme_scss_code = theme_scss_code.replace('%card_'+attribute+setting+'%',
                                                                  theme['card_'+attribute+setting])

            theme_scss_file = os.path.join(self.current_dir, '..', 'css', 'themes', themename+'.scss')
            epoch = datetime.datetime.utcnow()
            while (theme_scss_file in self.file_locks and
                   self.file_locks[theme_scss_file] > epoch - self.timedelta_minute):
                True

            self.file_locks[theme_scss_file] = datetime.datetime.utcnow()
            with open(theme_scss_file, 'w') as outfile:
                outfile.write(theme_scss_code)
                del self.file_locks[theme_scss_file]

            path_to_imports = [self.current_dir+os.sep+'..'+os.sep+'css'+os.sep]
            theme_css_code = scss.compiler.compile_string(theme_scss_code,
                                                          search_path=path_to_imports)
            theme_css_file = os.path.join(self.current_dir, '..', 'css', 'themes', themename+'.css')
            epoch = datetime.datetime.utcnow()
            while (theme_css_file in self.file_locks and
                   self.file_locks[theme_css_file] > epoch - self.timedelta_minute):
                True

            self.file_locks[theme_css_file] = datetime.datetime.utcnow()
            with open(theme_css_file, 'w') as outfile:
                outfile.write(theme_css_code)
                del self.file_locks[theme_css_file]

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

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

cherrypy.tree.mount(Themes(), '/themes', config=conf)
