#       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 ming import Session, mim
from ming.orm import state, session
from ming.orm.ormsession import ThreadLocalORMSession

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
    ThreadLocalORMSession.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()
    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)

    ThreadLocalORMSession.flush_all()
    ThreadLocalORMSession.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')
            ThreadLocalORMSession.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)

    ThreadLocalORMSession.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=[])
                                 ])

    ThreadLocalORMSession.flush_all()
    ThreadLocalORMSession.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')

    ThreadLocalORMSession.flush_all()
    ThreadLocalORMSession.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):
    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]
