""" 
    appinit.py
    
    Application configuration and initialisation.

    Do NOT modify any values in this file without first understanding, and
    making any necessary changes to, the code of the application.
    
    Copyright PR Hardman 2009 - 2023. 
    
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details./
    
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.

    
"""
import copy
import cherrypy

#~ from ppdb import config, config_db, config_ofb, uritree
from ppdb import config
from ppdb.handlers import (adminuri, appuri, sheepuri, ofburi, flockuri, memberuri, 
                                personuri, fbkuri, inspuri)

class Application():
    """ Class to provide common initialisation code for the OFB and Database"""
    
    CONFIG = {}
    CFGFILE = ''
   
    def __init__(self, ppdpath, dbparm, conf, login_life):
        """ Initialise the application instance """ 
        self.breed = None
        self.dbparm = dbparm
        self.CONFIG.update(conf)
        self.ppdpath = ppdpath
        self.tree = None
        self.config = {}
        self.appconf = {}
        self.cp_root = ''
        self.login_life = login_life

    def configure_app(self, baseconf):
        """ Configure the application:
            - Read the application's configuration file.
            - Merge the configuration with the values in the CONFIG dict.
        """
        
        # appconf is passed around to all the instantiated classes
        self.appconf = copy.deepcopy(config.ppdb_conf['breed_conf'])
        self.appconf['uri_root'] = ''
        self.appconf['domainbase'] = copy.copy(cherrypy.config['domainbase'])
        self.appconf.update(self.CONFIG)

        # Merge the breed conf with the base conf
        self.config = copy.deepcopy(baseconf)
                                            
    def build_tree(self):
        """ Build the uri tree. Implemented in the subclasses """
       
    def mount_app(self):
        """ Mount the application on CherryPy's tree. 
            Return the mounted app
        """
        return cherrypy.tree.mount(self.tree, '', self.config)

class AppInit(Application):
    """ The Unified app configuration and URI tree initialisation """
    CONFIG = {'fbk_start': 1973, 
                'appname': 'Online Flock Book',
                'shortname': 'Flock Book',}
                
    def build_tree(self):
        """ Build and configure the uri tree. 
            A branch's configuration is inherited by its twigs and leaves.
        """
        print("Building the uri tree")
        print(f"login life is {self.login_life} minutes")
        self.tree = appuri.AppRoot(self.appconf, 
                    {'tools.expires.on': True,
                        'tools.db_conn.on':True,
                        'tools.db_disc.on':True,
                        'tools.db_conn.dbparm': self.dbparm,
                        'tools.proxy.on': True,
                        'tools.check_auth.on': True,
                        'tools.check_auth.url_roles': {},
                        'tools.sessions.on': True,
                        'tools.sessions.secure': True,
                        'tools.sessions.httponly': True,
                        # This timeout will expire the session if there is no user activity
                        # during that period.
                        'tools.sessions.timeout': self.login_life,
                        'tools.sessions.name': 'SSS_Database',})
           
#~         self.tree.auth = appuri.Auth(self.appconf, {'tools.check_auth.on': False}) 
        self.tree.login = appuri.Login(self.appconf, {'tools.check_auth.on': False}) 
        self.tree.logout = appuri.Logout(self.appconf, {'tools.check_auth.on': False}) 
        self.tree.passwd = appuri.Password(self.appconf, {'tools.check_auth.on': False})
        self.tree.pwchange = appuri.PasswdChange(self.appconf, {'tools.check_auth.url_roles': 
                        {'GET': ('regsec', 'memsec', 'socsec', 'admin', 'member', 'breeder'),
                        'PUT': ('regsec', 'memsec', 'socsec', 'admin', 'member', 'breeder'),
                        'POST': (),
                        'DELETE': ()}})
        
        # The Admin branch                
        self.tree.admin = adminuri.Admin(self.appconf, {'tools.check_auth.url_roles': 
                                            {'GET': (),
                                            'PUT': (),
                                            'POST': ('admin'),
                                            'DELETE': ()}})
        self.tree.admin.access = adminuri.UserAccess(self.appconf, 
                                                        {'tools.check_auth.url_roles': 
                                                        {'GET': ('admin',),
                                                        'PUT': ('admin',),
                                                        'POST': ('admin',),
                                                        'DELETE': ('admin',)}})    

        # The sheep branch
        self.tree.sheep = sheepuri.Sheep(self.appconf, {'tools.check_auth.url_roles':
                                {'GET': ('regsec', 'memsec', 'socsec', 'admin'),
                                'PUT': ('regsec', 'admin',),
                                'POST': ('regsec', 'admin',),
                                'DELETE': ()}
                                })
                                
        self.tree.sheep.lookup = sheepuri.Lookup(self.appconf,
                                                    {'tools.check_auth.url_roles': None})
        self.tree.sheep.commanc = ofburi.CommonAncestors(self.appconf, 
                                                    {'tools.check_auth.url_roles': None})
        self.tree.sheep.pedigree = ofburi.Pedigree(self.appconf, 
                                                    {'tools.check_auth.url_roles': None})
        self.tree.sheep.progeny = ofburi.Progeny(self.appconf, 
                                                    {'tools.check_auth.url_roles': None})
        
        self.tree.sheep.aisire = sheepuri.AISire(self.appconf, 
                            {'tools.check_auth.url_roles': 
                                {'GET': ('regsec', 'admin'),
                                'PUT': ('regsec', 'admin'),
                                'POST': ('regsec', 'admin'),
                                'DELETE': ('regsec', 'admin')}})
        self.tree.sheep.certs = sheepuri.Certificates(self.appconf, 
                            {'tools.check_auth.url_roles': 
                                {'GET': ('regsec', 'admin'),
                                'PUT': ('regsec', 'admin'),
                                'POST': ('regsec', 'admin'),
                                'DELETE': ('regsec', 'admin')}})
        self.tree.sheep.info = sheepuri.Info(self.appconf, {'tools.check_auth.url_roles': 
                                {'GET': ('regsec', 'memsec', 'socsec', 'admin'),
                                'PUT': (),
                                'POST': (),
                                'DELETE': ()}})
        self.tree.sheep.find = sheepuri.Lookup(self.appconf, {'tools.check_auth.url_roles': 
                                {'GET': ('regsec', 'memsec', 'socsec', 'admin', 'breeder'),
                                'PUT': (),
                                'POST': (),
                                'DELETE': ()}})
        self.tree.sheep.nav = sheepuri.Nav(self.appconf, {'tools.check_auth.url_roles':
                                {'GET': ('regsec', 'memsec', 'socsec', 'admin', 'breeder'),
                                'PUT': ('regsec', 'admin',),
                                'POST': ('regsec', 'admin',),
                                'DELETE': ()}})
        self.tree.sheep.new = sheepuri.New(self.appconf, {'tools.check_auth.url_roles': 
                                {'GET': ('regsec', 'admin'),
                                'PUT': ('regsec', 'admin',),
                                'POST': ('regsec', 'admin',),
                                'DELETE': ()}})
        self.tree.sheep.tags = sheepuri.EarTag(self.appconf, {'tools.check_auth.url_roles': 
                                {'GET': ('regsec', 'memsec', 'socsec', 'admin'),
                                'PUT': ('regsec', 'admin'),
                                'POST': (),
                                'DELETE': ()}})
        self.tree.sheep.transfer = sheepuri.Transfer(self.appconf, 
                            {'tools.check_auth.url_roles': 
                                {'GET': ('regsec', 'memsec', 'socsec', 'admin'),
                                'PUT': ('regsec', 'admin',),
                                'POST': ('regsec', 'admin',),
                                'DELETE': ()}})
        self.tree.sheep.validator = sheepuri.Validators(self.appconf, 
                            {'tools.check_auth.url_roles': 
                                {'GET': ('regsec', 'memsec', 'socsec', 'admin'),
                                'PUT': ('regsec', 'admin',),
                                'POST': ('regsec', 'admin',),
                                'DELETE': ()}})

        # The inspections branch
        self.tree.insp = inspuri.Inspection(self.appconf, {'tools.check_auth.url_roles': 
                                {'GET': ('regsec', 'memsec', 'socsec', 'admin'),
                                'PUT': ('regsec', 'admin',),
                                'POST': (),
                                'DELETE': ()}})
        self.tree.insp.new = inspuri.New(self.appconf, {'tools.check_auth.url_roles': 
                                {'GET': ('regsec', 'admin'),
                                'PUT': (),
                                'POST': ('regsec', 'admin',),
                                'DELETE': ()}})
        self.tree.insp.validator = inspuri.Validators(self.appconf, 
                            {'tools.check_auth.url_roles': 
                                {'GET': ('regsec', 'admin'),
                                'PUT': (),
                                'POST': (),
                                'DELETE': ()}})
        self.tree.insp.venue = inspuri.Venue(self.appconf, {'tools.check_auth.url_roles': 
                                {'GET': ('regsec', 'admin'),
                                'PUT': (),
                                'POST': ('regsec', 'admin',),
                                'DELETE': ()}})
                                    
        # The Genotyping branch                                   
        self.tree.genetics = inspuri.Genotype(self.appconf, {'tools.check_auth.url_roles': 
                                {'GET': ('regsec', 'memsec', 'socsec', 'admin'),
                                'PUT': ('regsec', 'admin',),
                                'POST': ('regsec', 'admin',),
                                'DELETE': ()}})
        
        # The flock branch
        self.tree.flock = flockuri.Flock(self.appconf, {'tools.check_auth.url_roles': 
                                {'GET': ('regsec', 'memsec', 'socsec', 'admin', 'breeder'),
                                'PUT': ('memsec', 'admin',),
                                'POST': ('memsec', 'admin',),
                                'DELETE': ()}})
                                
        self.tree.flock.lookup = flockuri.Lookup(self.appconf, 
                                                    {'tools.check_auth.url_roles': None})
        self.tree.flock.maint = flockuri.Maint(self.appconf, {'tools.check_auth.url_roles': 
                                {'GET': ('regsec', 'memsec', 'socsec', 'admin'),
                                'PUT': ('memsec', 'admin'),
                                'POST': ('memsec', 'admin'),
                                'DELETE': ()}})
                                                    
        self.tree.flock.nav = flockuri.Nav(self.appconf, {'tools.check_auth.url_roles': 
                                {'GET': ('regsec', 'memsec', 'socsec', 'admin'),
                                'PUT': (),
                                'POST': (),
                                'DELETE': ()}})
        self.tree.flock.owner = flockuri.Owner(self.appconf, {'tools.check_auth.url_roles': 
                                {'GET': ('regsec', 'memsec', 'socsec', 'admin'),
                                'PUT': ('memsec', 'admin',),
                                'POST': ('memsec', 'admin',),
                                'DELETE': ()}})
        self.tree.flock.prefix = flockuri.Prefixes(self.appconf, 
                            {'tools.check_auth.url_roles': 
                                {'GET': ('regsec', 'memsec', 'socsec', 'admin'),
                                'PUT': ('regsec', 'admin',),
                                'POST': ('regsec', 'admin',),
                                'DELETE': ()}})
        self.tree.flock.regflk = flockuri.RegFlk(self.appconf, {'tools.check_auth.url_roles': 
                                {'GET': ('regsec', 'memsec', 'socsec', 'admin'),
                                'PUT': ('regsec', 'memsec', 'admin',),
                                'POST': ('regsec', 'memsec', 'admin',),
                                'DELETE': ()}})
        self.tree.flock.stats = flockuri.Stats(self.appconf, {'tools.check_auth.url_roles': 
                                {'GET': ('regsec', 'memsec', 'socsec', 'admin'),
                                'PUT': (),
                                'POST': (),
                                'DELETE': ()}})
        self.tree.flock.validator = flockuri.Validators(self.appconf, 
                            {'tools.check_auth.url_roles': 
                                {'GET': ('regsec', 'memsec', 'socsec', 'admin'),
                                'PUT': ('regsec', 'memsec', 'admin',),
                                'POST': ('regsec', 'memsec', 'admin',),
                                'DELETE': ()}})

        # The flockbook branch
        self.tree.fbk = fbkuri.FlockBook(self.appconf, {'tools.check_auth.url_roles': 
                                {'GET': ('regsec', 'memsec', 'socsec', 'admin'),
                                'PUT': (),
                                'POST': (),
                                'DELETE': ()}})
        self.tree.fbk.orders = fbkuri.Orders(self.appconf, {'tools.check_auth.url_roles': 
                                {'GET': ('regsec', 'socsec', 'admin'),
                                'PUT': ('regsec', 'admin',),
                                'POST': ('regsec', 'admin',),
                                'DELETE': ()}})
        self.tree.fbk.sheep = fbkuri.FbkSheep(self.appconf, {'tools.check_auth.url_roles': 
                                {'GET': ('regsec', 'memsec', 'socsec', 'admin'),
                                'PUT': (),
                                'POST': (),
                                'DELETE': ()}})
                                    
        # The member branch
        self.tree.member = memberuri.Member(self.appconf, {'tools.check_auth.url_roles': 
                        {'GET': ('memsec', 'regsec', 'socsec', 'admin', 'breeder', 'member'),
                       'PUT': ('memsec', 'admin',),
                       'POST': ('memsec', 'admin',),
                       'DELETE': ()}})
        self.tree.member.area = memberuri.Area(self.appconf, {'tools.check_auth.url_roles': 
                                {'GET': ('memsec', 'regsec', 'admin'),
                               'PUT': ('memsec', 'admin',),
                               'POST': ('memsec', 'admin',),
                               'DELETE': ('memsec', 'admin',)}})
        self.tree.member.maint = memberuri.Maint(self.appconf, {'tools.check_auth.url_roles': 
                                {'GET': ('memsec', 'admin'),
                               'PUT': ('memsec', 'admin',),
                               'POST': ('memsec', 'admin',),
                               'DELETE': ()}})
        self.tree.member.lookup = memberuri.Lookup(self.appconf, 
                            {'tools.check_auth.url_roles': 
                                {'GET': ('memsec', 'regsec', 'socsec', 'admin'),
                                'PUT': (),
                                'POST': (),
                                'DELETE': ()}})
        self.tree.member.nav = memberuri.Nav(self.appconf, {'tools.check_auth.url_roles': 
                                {'GET': ('memsec', 'regsec', 'socsec', 'admin'),
                                'PUT': (),
                                'POST': (),
                                'DELETE': ()}})
        self.tree.member.reports = memberuri.Reports(self.appconf, 
                            {'tools.check_auth.url_roles': 
                                {'GET': ('memsec', 'regsec', 'socsec', 'admin'),
                                'PUT': ('memsec', 'regsec', 'socsec', 'admin',),
                                'POST': ('memsec', 'regsec', 'socsec', 'admin',),
                                'DELETE': ()}})
        self.tree.member.stats = memberuri.Stats(self.appconf, {'tools.check_auth.url_roles': 
                                {'GET': ('memsec', 'regsec', 'socsec', 'admin'),
                                'PUT': (),
                                'POST': (),
                                'DELETE': ()}})
        # The person branch
        self.tree.person = personuri.Person(self.appconf, {'tools.check_auth.url_roles': 
                                {'GET': ('memsec', 'regsec', 'socsec', 'admin'),
                                'PUT': ('memsec', 'admin',),
                                'POST': ('memsec', 'admin',),
                                'DELETE': ('admin',)}})
        self.tree.person.email = personuri.Email(self.appconf, {'tools.check_auth.url_roles': 
                                {'GET': ('memsec', 'socsec', 'admin'),
                                'PUT': ('memsec', 'admin',),
                                'POST': ('memsec', 'admin',),
                                'DELETE': ('memsec', 'admin',)}})
        self.tree.person.phone = personuri.Phone(self.appconf, {'tools.check_auth.url_roles': 
                                {'GET': ('memsec', 'socsec', 'admin'),
                                'PUT': ('memsec', 'admin',),
                                'POST': ('memsec', 'admin',),
                                'DELETE': ('memsec', 'admin',)}})
        self.tree.person.role = personuri.Role(self.appconf, {'tools.check_auth.url_roles': 
                                {'GET': ('memsec', 'regsec', 'socsec', 'admin'),
                               'PUT': ('memsec', 'admin',),
                               'POST': ('memsec', 'admin',),
                               'DELETE': ('memsec', 'admin')}})
        self.tree.person.selpers = personuri.SelPers(self.appconf, 
                            {'tools.check_auth.url_roles': 
                                {'GET': ('memsec', 'regsec', 'socsec', 'admin'),
                                'PUT': ('memsec', 'regsec', 'socsec', 'admin',),
                                'POST': ('memsec', 'regsec', 'socsec', 'admin',),
                                'DELETE': ('memsec', 'regsec', 'socsec', 'admin',)},})
        # The user branch
        self.tree.person.user = personuri.User(self.appconf, {'tools.check_auth.url_roles': 
                                {'GET': ('member', 'breeder'),
                                'PUT': (),
                                'POST': (),
                                'DELETE': ()}})
