# coding: utf-8

from __future__ import unicode_literals

from django import forms
from django.utils import timezone

from ids.services.formatter import structure

from cab.core import widgets
from cab.sources import wiki, calendar
from cab.utils import validators


MEETINGS_PAGE_TAG_PATTERN = '/users/{auth_login}/notes/meetings/{login}'


class MeetingsInfo(widgets.BaseEndpointHandler):

    class Validator(validators.WidgetValidator):
        login = validators.LoginField()

    def handle(self, data):
        login = data['login']
        response_data = {}
        response_data.update(self.get_last_note(login))
        response_data.update(self.get_next_meeting(login))
        return response_data

    def get_last_note(self, login):
        tag = get_meetings_page_tag(self.auth, login)
        page_structure = wiki.get_page_structure(auth=self.auth, tag=tag)
        if page_structure is None:
            return {}

        first_header_data = get_header_data(page_structure=page_structure)
        if first_header_data is None:
            return {}

        markup = wiki.get_page_markup(auth=self.auth, tag=tag)
        note = markup[
            first_header_data['text_pos_start']:
            first_header_data['text_pos_end']
        ]
        note = note.strip('\n')

        return build_response_json(
            auth=self.auth,
            login=login,
            wiki_text=note,
            date_str=first_header_data['text'],
            anchor=first_header_data['anchor'],
        )

    def get_next_meeting(self, login):
        events = calendar.get_events(auth=self.auth)

        for event in events:
            attendees = event.get('attendees', [])
            organizer = event.get('organizer', {})
            on_meeting = attendees + [organizer]
            on_meeting_logins = {user.get('login') for user in on_meeting}

            if on_meeting_logins == {login, self.auth.login}:
                meeting_data = {
                    'start': event['startTs'],
                    'name': event['name']
                }
                resources = event.get('resources', [])
                if resources:
                    meeting_data['room'] = resources[0].get('name', '')
                return {'next_meeting': meeting_data}
        return {}


class AddNote(widgets.BaseEndpointHandler):

    class Validator(validators.WidgetValidator):
        login = validators.LoginField(required=True)
        text = forms.CharField()
        anchor = forms.CharField(required=False)

    def handle(self, data):
        login = data['login']

        today_str = get_today_str()
        new_note = data['text']
        anchor = data['anchor']

        if not anchor:
            result = self.add_new_note(login=login, new_note=new_note)
            date_str = today_str
            anchor = today_str
        else:
            result = self.replace_note_for_anchor(
                login=login,
                new_note=new_note,
                anchor=anchor,
            )
            date_str = anchor[:len('YYYY-MM-DD')]
        if result.ok:
            return build_response_json(
                auth=self.auth,
                login=login,
                wiki_text=new_note,
                date_str=date_str,
                anchor=anchor,
            )
        else:
            return {
                'errors': result.json()
            }

    def add_new_note(self, login, new_note):
        tag = get_meetings_page_tag(self.auth, login)
        body = wiki.get_page_markup(auth=self.auth, tag=tag)
        if body is None:
            exists = False
            body = ''
        else:
            exists = True
        updated_body = '==' + get_today_str() + '\n' + new_note + '\n' + body
        response = wiki.update_page(
            auth=self.auth,
            tag=tag,
            title=get_meetings_page_title(login=login),
            body=updated_body,
        )
        if not response.ok:
            return response

        if not exists:
            response = wiki.set_page_access(
                auth=self.auth,
                tag=tag,
                type='owner',
            )
        return response

    def replace_note_for_anchor(self, login, new_note, anchor):
        tag = get_meetings_page_tag(self.auth, login)
        body = wiki.get_page_markup(auth=self.auth, tag=tag) or ''
        page_structure = wiki.get_page_structure(auth=self.auth, tag=tag)
        header_data = get_header_data(
            page_structure=page_structure,
            anchor=anchor,
        )
        if header_data is None:
            return self.add_new_note(login, new_note)

        start = header_data['text_pos_start']
        end = header_data['text_pos_end']
        updated_body = body[:start] + new_note + '\n' + body[end:]

        return wiki.update_page(
            auth=self.auth,
            tag=tag,
            title=get_meetings_page_title(login=login),
            body=updated_body,
        )


def get_header_data(page_structure, anchor=None):
    page_structure = structure.wrap_wiki_node(node=page_structure)
    headers = page_structure.filter('head')

    required_header = None
    if anchor is None:
        required_header = next(headers, None)
    else:
        for header in headers:
            header_anchor = header.attrs.anchor
            if anchor == header_anchor:
                required_header = header
                break

    if required_header is None:
        return

    next_header = next(headers, None)

    # start:end должны правильно подходить для слайса строки вики-текста
    inner_text_start = required_header.attrs['pos_end'] + 1
    innert_text_end = (
        next_header and next_header.attrs['pos_start']
        or page_structure.attrs['pos_end']
    )
    return {
        'text': required_header.content[0].attrs['txt'],
        'anchor': required_header.attrs.anchor,
        'text_pos_start': inner_text_start,
        'text_pos_end': innert_text_end,
    }


def get_today_str():
    return timezone.now().date().isoformat()


def get_meetings_page_tag(auth, login):
    return MEETINGS_PAGE_TAG_PATTERN.format(
        auth_login=auth.login,
        login=login,
    )


def get_meetings_page_title(login):
    return 'Встречи с @{}'.format(login)


def get_meetings_page_url(auth, login):
    tag = get_meetings_page_tag(auth, login)
    url = wiki.RESOURCES['page_web'].format(tag=tag)
    return url


def build_response_json(auth, login, wiki_text, date_str, anchor):
    return {
        'last_note': {
            'url': get_meetings_page_url(auth=auth, login=login),
            'text': wiki_text,
            'html': wiki.markup_to_html(wiki_text),
            'date': date_str,
            'anchor': anchor,
        }
    }


class MeetingsWidget(widgets.BaseWidget):
    id = 'personal_meetings'

    endpoints = {
        'root': {
            'regex': '/$',
            'handler': {
                'GET': MeetingsInfo,
                'POST': AddNote,
            }
        },
    }
