#       Licensed to the Apache Software Foundation (ASF) under one
#       or more contributor license agreements.  See the NOTICE file
#       distributed with this work for additional information
#       regarding copyright ownership.  The ASF licenses this file
#       to you under the Apache License, Version 2.0 (the
#       "License"); you may not use this file except in compliance
#       with the License.  You may obtain a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#       Unless required by applicable law or agreed to in writing,
#       software distributed under the License is distributed on an
#       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
#       KIND, either express or implied.  See the License for the
#       specific language governing permissions and limitations
#       under the License.

"""Setup the allura application"""
import os
import sys
import logging
import shutil
from textwrap import dedent

import tg
from tg import tmpl_context as c, app_globals as g
from paste.deploy.converters import asbool
import ew

from allura.model.oauth import dummy_oauths
from ming import Session, mim
from ming.odm import state, session
from ming.odm.odmsession import ThreadLocalODMSession

import allura
from allura.lib import plugin
from allura.lib import helpers as h
from allura import model as M
from allura.command import EnsureIndexCommand
from allura.command import CreateTroveCategoriesCommand
from allura.websetup.schema import REGISTRY

from forgewiki import model as WM
import six

log = logging.getLogger(__name__)


def bootstrap(command, conf, vars):
    """Place any commands to setup allura here"""
    # are we being called by the test suite?
    test_run = conf.get('__file__', '').endswith('test.ini')

    if not test_run:
        # when this is run via the `setup-app` cmd, some macro rendering needs this set up
        REGISTRY.register(ew.widget_context,
                          ew.core.WidgetContext('http', ew.ResourceManager()))

    create_test_data = asbool(os.getenv('ALLURA_TEST_DATA', 'true'))

    # if this is a test_run, skip user project creation to save time
    make_user_projects = not test_run

    def make_user(*args, **kw):
        kw.update(make_project=make_user_projects)
        return create_user(*args, **kw)

    # Temporarily disable auth extensions to prevent unintended side-effects
    tg.config['auth.method'] = tg.config['registration.method'] = 'local'
    assert tg.config['auth.method'] == 'local'
    conf['auth.method'] = conf['registration.method'] = 'local'

    # Clean up all old stuff
    ThreadLocalODMSession.close_all()
    c.user = c.project = c.app = None
    wipe_database()
    try:
        g.solr.delete(q='*:*')
    except Exception:  # pragma no cover
        log.error('SOLR server is %s', g.solr_server)
        log.error('Error clearing solr index')

    # set up mongo indexes
    index = EnsureIndexCommand('ensure_index')
    index.run([''])

    log.info('Registering root user & default neighborhoods')
    anon = M.User.anonymous_uncached()
    session(M.User).save(anon)

    # never make a user project for the root user
    if create_test_data:
        root = create_user('Root', make_project=False)
    else:
        from getpass import getpass
        root_name = input('Enter username for root user (default "root"): ').strip()
        if not root_name:
            root_name = 'root'
        ok = False
        while not ok:
            root_password1 = getpass('Enter password: ')
            if len(root_password1) == 0:
                log.info('Password must not be empty')
                continue
            root_password2 = getpass('Confirm password: ')
            if root_password1 != root_password2:
                log.info("Passwords don't match")
                continue
            root = create_user(root_name, password=root_password1, make_project=False)
            ok = True

    n_projects = M.Neighborhood(name='Projects', url_prefix='/p/',
                                features=dict(private_projects=True,
                                              max_projects=None,
                                              css='none',
                                              google_analytics=False))
    n_users = M.Neighborhood(name='Users', url_prefix='/u/',
                             shortname_prefix='u/',
                             anchored_tools='profile:Profile,userstats:Statistics',
                             features=dict(private_projects=True,
                                           max_projects=None,
                                           css='none',
                                           google_analytics=False))

    assert tg.config['auth.method'] == 'local'
    project_reg = plugin.ProjectRegistrationProvider.get()
    p_projects = project_reg.register_neighborhood_project(
        n_projects, [root], allow_register=True)
    p_users = project_reg.register_neighborhood_project(n_users, [root])

    def set_nbhd_wiki_content(nbhd_proj, content):
        wiki = nbhd_proj.app_instance('wiki')
        page = WM.Page.query.get(
            app_config_id=wiki.config._id, title=wiki.root_page_name)
        page.text = content

    set_nbhd_wiki_content(p_projects, dedent('''
        Welcome to the "Projects" neighborhood.  It is the default neighborhood in Allura.
        You can edit this wiki page as you see fit.  Here's a few ways to get started:

        [Register a new project](/p/add_project)

        [Neighborhood administration](/p/admin)

        [[projects show_total=yes]]
        '''))
    set_nbhd_wiki_content(p_users, dedent('''
        This is the "Users" neighborhood.
        All users automatically get a user-project created for them, using their username.

        [Neighborhood administration](/u/admin)

        [[projects show_total=yes]]
        '''))
    if create_test_data:
        n_adobe = M.Neighborhood(
            name='Adobe', url_prefix='/adobe/', project_list_url='/adobe/',
            features=dict(private_projects=True,
                          max_projects=None,
                          css='custom',
                          google_analytics=True))
        p_adobe = project_reg.register_neighborhood_project(n_adobe, [root])
        set_nbhd_wiki_content(p_adobe, dedent('''
            This is the "Adobe" neighborhood.  It is just an example of having projects in a different neighborhood.

            [Neighborhood administration](/adobe/admin)

            [[projects show_total=yes]]
            '''))
        # add the adobe icon
        file_name = 'adobe_icon.png'
        file_path = os.path.join(
            allura.__path__[0], 'public', 'nf', 'images', file_name)
        M.NeighborhoodFile.from_path(file_path, neighborhood_id=n_adobe._id)

    ThreadLocalODMSession.flush_all()
    ThreadLocalODMSession.close_all()

    if create_test_data:
        # Add some test users
        for unum in range(10):
            make_user('Test User %d' % unum)

    log.info('Creating basic project categories')
    M.ProjectCategory(name='clustering', label='Clustering')
    cat2 = M.ProjectCategory(name='communications', label='Communications')
    M.ProjectCategory(
        name='synchronization', label='Synchronization', parent_id=cat2._id)
    M.ProjectCategory(
        name='streaming', label='Streaming', parent_id=cat2._id)
    M.ProjectCategory(name='fax', label='Fax', parent_id=cat2._id)
    M.ProjectCategory(name='bbs', label='BBS', parent_id=cat2._id)

    cat3 = M.ProjectCategory(name='database', label='Database')
    M.ProjectCategory(
        name='front_ends', label='Front-Ends', parent_id=cat3._id)
    M.ProjectCategory(
        name='engines_servers', label='Engines/Servers', parent_id=cat3._id)

    if create_test_data:
        log.info('Registering "regular users" (non-root) and default projects')
        # since this runs a lot for tests, separate test and default users and
        # do the minimal needed
        if asbool(conf.get('load_test_data')):
            u_admin = make_user('Test Admin')
            u_admin.preferences = dict(email_address='test-admin@users.localhost')
            u_admin.email_addresses = ['test-admin@users.localhost']
            u_admin.set_password('foo')
            u_admin.claim_address('test-admin@users.localhost')
            ThreadLocalODMSession.flush_all()

            admin_email = M.EmailAddress.get(email='test-admin@users.localhost')
            admin_email.confirmed = True
        else:
            u_admin = make_user('Admin 1', username='admin1')
            # Admin1 is almost root, with admin access for Users and Projects
            # neighborhoods
            p_projects.add_user(u_admin, ['Admin'])
            p_users.add_user(u_admin, ['Admin'])

            n_projects.register_project('allura', u_admin, 'Allura')
        make_user('Test User')
        n_adobe.register_project('adobe-1', u_admin, 'Adobe project 1')
        p_adobe.add_user(u_admin, ['Admin'])
        p0 = n_projects.register_project('test', u_admin, 'Test Project')
        n_projects.register_project('test2', u_admin, 'Test 2')
        p0._extra_tool_status = ['alpha', 'beta']

    sess = session(M.Neighborhood)  # all the sessions are the same
    _list = (n_projects, n_users, p_projects, p_users)
    if create_test_data:
        _list += (n_adobe, p_adobe)
    for x in _list:
        # Ming doesn't detect substructural changes in newly created objects
        # (vs loaded from DB)
        state(x).status = 'dirty'
        # TODO: Hope that Ming can be improved to at least avoid stuff below
        sess.flush(x)

    ThreadLocalODMSession.flush_all()

    if not asbool(conf.get('load_test_data')):
        # regular first-time setup

        create_trove_categories = CreateTroveCategoriesCommand('create_trove_categories')
        create_trove_categories.run([''])

        if create_test_data:
            p0.add_user(u_admin, ['Admin'])
            log.info('Registering initial apps')
            with h.push_config(c, user=u_admin):
                p0.install_apps([{'ep_name': ep_name}
                                 for ep_name, app in g.entry_points['tool'].items()
                                 if app._installable(tool_name=ep_name,
                                                     nbhd=n_projects,
                                                     project_tools=[])
                                 ])

    ThreadLocalODMSession.flush_all()
    ThreadLocalODMSession.close_all()

    if create_test_data:
        # reload our p0 project so that p0.app_configs is accurate with all the
        # newly installed apps
        p0 = M.Project.query.get(_id=p0._id)
        sub = p0.new_subproject('sub1', project_name='A Subproject')
        with h.push_config(c, user=u_admin):
            sub.install_app('wiki')

    if not test_run:
        # only when running setup-app do we need this.  the few tests that need it do it themselves
        dummy_oauths()

    ThreadLocalODMSession.flush_all()
    ThreadLocalODMSession.close_all()


def wipe_database():
    conn = M.main_doc_session.bind.conn
    if isinstance(conn, mim.Connection):
        clear_all_database_tables()
        for db in conn.database_names():
            db = conn[db]
    else:
        for database in conn.database_names():
            if database not in ('allura', 'pyforge', 'project-data'):
                continue
            log.info('Wiping database %s', database)
            db = conn[database]
            for coll in list(db.collection_names()):
                if coll.startswith('system.'):
                    continue
                log.info('Dropping collection %s:%s', database, coll)
                try:
                    db.drop_collection(coll)
                except Exception:
                    pass


def clear_all_database_tables():
    conn = M.main_doc_session.bind.conn
    for db in conn.database_names():
        db = conn[db]
        for coll in list(db.collection_names()):
            if coll == 'system.indexes':
                continue
            db.drop_collection(coll)


def create_user(display_name, username=None, password='foo', make_project=False):  # noqa: S107
    if not username:
        username = display_name.lower().replace(' ', '-')
    user = M.User.register(dict(username=username,
                                display_name=display_name),
                           make_project=make_project)
    email = username+"@allura.local"
    user.claim_address(email)
    from allura.model.auth import EmailAddress
    kw = {"email": email}
    em = EmailAddress.get(**kw)
    em.confirmed = True
    em.set_nonce_hash()
    user.set_pref('email_address',email)
    user.set_password(password)
    return user


class DBSession(Session):

    '''Simple session that takes a pymongo connection and a database name'''

    def __init__(self, db):
        self._db = db

    @property
    def db(self):
        return self._db

    def _impl(self, cls):
        return self.db[cls.__mongometa__.name]
