#       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.
from bs4 import BeautifulSoup
import mock

from tg import config
from nose.tools import assert_equals, assert_true, assert_in, assert_equal
from ming.orm import session

from allura import model as M
from allura.lib import helpers as h
from allura.tests import TestController
from alluratest.controller import setup_trove_categories
from allura.tests import decorators as td


class TestTroveCategory(TestController):
    @mock.patch('allura.model.project.g.post_event')
    def test_events(self, post_event):
        setup_trove_categories()

        # Create event
        cfg = {'trovecategories.enableediting': 'true'}
        with h.push_config(config, **cfg):
            r = self.app.post('/categories/create/', params=dict(categoryname='test'))

        category_id = post_event.call_args[0][1]
        assert_true(isinstance(category_id, int))
        assert_equals(post_event.call_args[0][0], 'trove_category_created')
        category = M.TroveCategory.query.get(trove_cat_id=category_id)

        # Update event
        category.fullname = 'test2'
        session(M.TroveCategory).flush()
        edited_category_id = post_event.call_args[0][1]
        assert_true(isinstance(edited_category_id, int))
        assert_equals(edited_category_id, category_id)
        assert_equals(post_event.call_args[0][0], 'trove_category_updated')

        # Delete event
        M.TroveCategory.delete(category)
        session(M.TroveCategory).flush()
        deleted_category_id = post_event.call_args[0][1]
        assert_true(isinstance(deleted_category_id, int))
        assert_equals(deleted_category_id, category_id)
        assert_equals(post_event.call_args[0][0], 'trove_category_deleted')

    def test_enableediting_setting(self):
        def check_access(username=None, status=None):
            self.app.get('/categories/', status=status,
                         extra_environ=dict(username=username))

        cfg = {'trovecategories.enableediting': 'true'}

        with h.push_config(config, **cfg):
            check_access(username='test-user', status=200)
            check_access(username='root', status=200)

        cfg['trovecategories.enableediting'] = 'false'
        with h.push_config(config, **cfg):
            check_access(username='test-user', status=403)
            check_access(username='root', status=403)

        cfg['trovecategories.enableediting'] = 'admin'
        with h.push_config(config, **cfg):
            check_access(username='test-user', status=403)
            check_access(username='root', status=200)


class TestTroveCategoryController(TestController):
    def create_some_cats(self):
        root_parent = M.TroveCategory(fullname="Root", trove_cat_id=1, trove_parent_id=0)
        category_a = M.TroveCategory(fullname="CategoryA", trove_cat_id=2, trove_parent_id=1)
        category_b = M.TroveCategory(fullname="CategoryB", trove_cat_id=3, trove_parent_id=1)
        child_a = M.TroveCategory(fullname="ChildA", trove_cat_id=4, trove_parent_id=2)
        child_b = M.TroveCategory(fullname="ChildB", trove_cat_id=5, trove_parent_id=2)

    def test_root(self):
        self.create_some_cats()
        session(M.TroveCategory).flush()
        r = self.app.get('/categories/')
        assert '<a href="/categories/1">Root</a>' in r

    def test_subcat(self):
        self.create_some_cats()
        session(M.TroveCategory).flush()
        r = self.app.get('/categories/1')
        assert '<a href="/categories/2">CategoryA</a>' in r
        assert '<a href="/categories/3">CategoryB</a>' in r

    @td.with_tool('test2', 'admin_main', 'admin')
    def test_trove_hierarchy(self):
        self.create_some_cats()
        session(M.TroveCategory).flush()

        r = self.app.get('/categories/browse')
        rendered_tree = r.html.find('div', {'id': 'content_base'}).find('div').find('div').find('ul')
        expected = BeautifulSoup("""
        <ul>
            <li>Root</li>
            <ul>
                <li>CategoryA</li>
                <ul>
                    <li>ChildA</li>
                    <li>ChildB</li>
                </ul>
                <li>CategoryB</li>
            </ul>
        </ul>
        """.strip(), 'html.parser')
        assert_equals(str(expected), str(rendered_tree))

    @td.with_tool('test2', 'admin_main', 'admin')
    def test_trove_empty_hierarchy(self):
        r = self.app.get('/categories/browse')
        rendered_tree = r.html.find('div', {'id': 'content_base'}).find('div').find('div').find('ul')
        expected = BeautifulSoup("""
        <ul>
        </ul>
        """.strip(), 'html.parser')
        assert_equals(str(expected), str(rendered_tree))

    def test_delete(self):
        self.create_some_cats()
        session(M.TroveCategory).flush()
        assert_equals(5, M.TroveCategory.query.find().count())

        r = self.app.get('/categories/1')
        form = r.forms[0]
        r = form.submit()
        assert_in("This category contains at least one sub-category, therefore it can't be removed",
                  self.webflash(r))

        r = self.app.get('/categories/2')
        form = r.forms[0]
        r = form.submit()
        assert_in("Category removed", self.webflash(r))
        assert_equals(4, M.TroveCategory.query.find().count())

    def test_create_parent(self):
        self.create_some_cats()
        session(M.TroveCategory).flush()
        r = self.app.get('/categories/')

        form = r.forms[1]
        form['categoryname'].value = "New Category"
        form.submit()

        possible = M.TroveCategory.query.find(dict(fullname='New Category')).all()
        assert_equal(len(possible), 1)
        assert_equal(possible[0].fullname, 'New Category')
        assert_equal(possible[0].shortname, 'new-category')

    def test_create_child(self):
        self.create_some_cats()
        session(M.TroveCategory).flush()
        r = self.app.get('/categories/2')

        form = r.forms[2]
        form['categoryname'].value = "New Child"
        form.submit()

        possible =M.TroveCategory.query.find(dict(fullname='New Child')).all()
        assert_equal(len(possible), 1)
        assert_equal(possible[0].fullname, 'New Child')
        assert_equal(possible[0].shortname, 'new-child')
        assert_equal(possible[0].trove_parent_id, 2)

        # test slugify with periods. the relevant form becomes the third, after a child has been created above.
        r = self.app.get('/categories/2')
        form = r.forms[3]
        form['categoryname'].value = "New Child.io"
        form.submit()
        possible = M.TroveCategory.query.find(dict(fullname='New Child.io')).all()
        assert_equal(possible[0].shortname, 'new-child.io')

    def test_create_child_bad_upper(self):
        self.create_some_cats()
        session(M.TroveCategory).flush()
        r = self.app.get('/categories/2')

        form = r.forms[2]
        form['categoryname'].value = "New Child"
        form['uppercategory_id'].value = "541561615"
        r = form.submit().follow()

        assert 'Invalid upper category' in r.text
