# -*- coding: utf-8 -*-

#       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.

import os
import StringIO
import allura
import json

import PIL
from nose.tools import assert_true, assert_equal, assert_in, assert_not_equal, assert_not_in
from ming.orm.ormsession import ThreadLocalORMSession
from mock import patch
from tg import config

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

from forgewiki import model


class TestRootController(TestController):

    def setUp(self):
        super(TestRootController, self).setUp()
        self.setup_with_tools()

    @td.with_wiki
    def setup_with_tools(self):
        pass

    def _find_edit_form(self, resp):
        def cond(f):
            return f.id == 'page_edit_form'
        return self.find_form(resp, cond)

    def test_root_index(self):
        page_url = h.urlquote(u'/wiki/tést/')
        r = self.app.get(page_url).follow()
        assert u'tést' in r
        assert 'Create Page' in r
        # No 'Create Page' button if user doesn't have 'create' perm
        r = self.app.get('/wiki/Home',
                         extra_environ=dict(username='*anonymous'))
        assert 'Create Page' not in r, r

    @td.with_wiki
    def test_create_wiki_page(self):
        url = u"/p/test/wiki/create_wiki_page/"
        r = self.app.get(url)
        assert u'test' in r
        assert u'Create page' in r.body

    def test_root_markdown_syntax(self):
        response = self.app.get('/wiki/markdown_syntax/')
        assert 'Markdown Syntax' in response

    def test_root_browse_tags(self):
        response = self.app.get('/wiki/browse_tags/')
        assert 'Browse Labels' in response

    def test_root_browse_pages(self):
        response = self.app.get('/wiki/browse_pages/')
        assert 'Browse Pages' in response

    def test_root_new_page(self):
        response = self.app.get('/wiki/new_page?title=' + h.urlquote(u'tést'))
        assert u'tést' in response

    def test_root_new_search(self):
        self.app.get(h.urlquote(u'/wiki/tést/'))
        response = self.app.get('/wiki/search/?q=' + h.urlquote(u'tést'))
        assert u'Search wiki: tést' in response

    def test_feed(self):
        for ext in ['', '.rss', '.atom']:
            self.app.get('/wiki/feed%s' % ext, status=200)

    @patch('allura.lib.search.search')
    def test_search(self, search):
        r = self.app.get('/wiki/search/?q=test')
        assert_in(
            '<a href="/wiki/search/?q=test&amp;sort=score+asc" class="strong">relevance</a>', r)
        assert_in(
            '<a href="/wiki/search/?q=test&amp;sort=mod_date_dt+desc" class="">date</a>', r)

        p = M.Project.query.get(shortname='test')
        r = self.app.get('/wiki/search/?q=test&sort=score+asc')
        solr_query = {
            'short_timeout': True,
            'ignore_errors': False,
            'rows': 25,
            'start': 0,
            'qt': 'dismax',
            'qf': 'title^2 text',
            'pf': 'title^2 text',
            'fq': [
                'project_id_s:%s' % p._id,
                'mount_point_s:wiki',
                '-deleted_b:true',
                'type_s:("WikiPage" OR "WikiPage Snapshot")',
                'is_history_b:False',
            ],
            'hl': 'true',
            'hl.simple.pre': '#ALLURA-HIGHLIGHT-START#',
            'hl.simple.post': '#ALLURA-HIGHLIGHT-END#',
            'sort': 'score asc',
        }
        search.assert_called_with('test', **solr_query)

        r = self.app.get(
            '/wiki/search/?q=test&search_comments=on&history=on&sort=mod_date_dt+desc')
        solr_query['fq'][
            3] = 'type_s:("WikiPage" OR "WikiPage Snapshot" OR "Post")'
        solr_query['fq'].remove('is_history_b:False')
        solr_query['sort'] = 'mod_date_dt desc'
        search.assert_called_with('test', **solr_query)

        r = self.app.get('/wiki/search/?q=test&parser=standard')
        solr_query['sort'] = 'score desc'
        solr_query['fq'][3] = 'type_s:("WikiPage" OR "WikiPage Snapshot")'
        solr_query['fq'].append('is_history_b:False')
        solr_query.pop('qt')
        solr_query.pop('qf')
        solr_query.pop('pf')
        search.assert_called_with('test', **solr_query)

    def test_search_help(self):
        r = self.app.get('/wiki/search/?q=test')
        btn = r.html.find('a', attrs={'class': 'icon btn search_help_modal'})
        assert btn is not None, "Can't find a help button"
        div = r.html.find('div', attrs={'id': 'lightbox_search_help_modal'})
        assert div is not None, "Can't find help text"
        assert_in('To search for an exact phrase', div.text)


    def test_nonexistent_page_edit(self):
        resp = self.app.get('/wiki/tést/')
        assert resp.location.endswith(h.urlquote(u'/wiki/tést/edit')), 
resp.location
        resp = resp.follow()
        assert 'tést' in resp

    def test_nonexistent_page_noedit(self):
        self.app.get('/wiki/tést/',
                     extra_environ=dict(username='*anonymous'),
                     status=404)
        self.app.get('/wiki/tést/',
                     extra_environ=dict(username='test-user'),
                     status=404)

    @patch('forgewiki.wiki_main.g.director.create_activity')
    def test_activity(self, create_activity):
        d = dict(title='foo', text='footext')
        self.app.post('/wiki/foo/update', params=d)
        assert create_activity.call_count == 1
        assert create_activity.call_args[0][1] == 'created'
        create_activity.reset_mock()
        d = dict(title='foo', text='new footext')
        self.app.post('/wiki/foo/update', params=d)
        assert create_activity.call_count == 1
        assert create_activity.call_args[0][1] == 'modified'
        create_activity.reset_mock()
        d = dict(title='new foo', text='footext')
        self.app.post('/wiki/foo/update', params=d)
        assert create_activity.call_count == 1
        assert create_activity.call_args[0][1] == 'renamed'

    def test_labels(self):
        response = self.app.post(
            '/wiki/foo-bar/update',
            params={
                'title': 'foo',
                'text': 'sometext',
                'labels': 'test label',
                'viewable_by-0.id': 'all'}).follow()
        assert_in('<a href="/p/test/wiki/search/?q=labels_t:%22test label%22&parser=standard">test label (1)</a>',
                  response)

    def test_title_slashes(self):
        # forward slash not allowed in wiki page title - converted to dash
        response = self.app.post(
            '/wiki/foo-bar/update',
            params={
                'title': 'foo/bar',
                'text': 'sometext',
                'labels': '',
                'viewable_by-0.id': 'all'}).follow()
        assert 'foo-bar' in response
        assert 'foo-bar' in response.request.url

    def test_dotted_page_name(self):
        r = self.app.post(
            '/wiki/page.dot/update',
            params={
                'title': 'page.dot',
                'text': 'text1',
                'labels': '',
                'viewable_by-0.id': 'all'}).follow()
        assert 'page.dot' in r

    def test_subpage_attempt(self):
        self.app.get('/wiki/tést/')
        self.app.post(
            '