from reportlab.platypus import (
    BaseDocTemplate,
    Frame,
    Paragraph,
    PageTemplate,
    FrameBreak,
    Spacer,
    PageBreak,
)
from reportlab.lib.units import mm
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.pagesizes import A4
from reportlab.lib.enums import TA_CENTER, TA_RIGHT
from reportlab.lib.fonts import addMapping
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont

from django.conf import settings
from django.utils.datetime_safe import date
from django.utils.translation import override
from django.utils.formats import date_format

from staff.lib.requests import get_ids_repository
from staff.person.models import Staff

from staff.lib.utils.qs_values import extract_related


# Регестрируем два начертания шрифта
pdfmetrics.registerFont(
    TTFont(
        'DejaVuSerif',
        '/usr/share/fonts/truetype/ttf-dejavu/DejaVuSerif.ttf'
    )
)
pdfmetrics.registerFont(
    TTFont(
        'DejaVuSerifB',
        '/usr/share/fonts/truetype/ttf-dejavu/DejaVuSerif-Bold.ttf'
    )
)

addMapping('DejaVuSerif', 0, 0, 'DejaVuSerif')
addMapping('DejaVuSerif', 1, 0, 'DejaVuSerifB')
addMapping('DejaVuSerif', 0, 1, 'DejaVuSerif')
addMapping('DejaVuSerif', 1, 1, 'DejaVuSerifB')


def gen_pdf(file_object, gaps_data):

    # Создаем наш документ
    doc = BaseDocTemplate(
        file_object,
        leftMargin=10*mm,
        rightMargin=10*mm,
        bottomMargin=10*mm,
        topMargin=10*mm,
        pagesize=A4,
        showBoundary=0,
    )

    frame_head = Frame(
        id='head',
        x1=doc.leftMargin + doc.width // 2,
        y1=doc.bottomMargin + doc.height - 50*mm,
        width=95*mm,
        height=50*mm,
    )
    frame_body = Frame(
        id='body',
        x1=doc.leftMargin,
        y1=doc.bottomMargin + 110*mm,
        width=doc.width,
        height=70*mm,
    )
    frame_signature = Frame(
        id='signature',
        x1=doc.leftMargin,
        y1=doc.bottomMargin,
        width=doc.width,
        height=85*mm,
    )

    def on_page(canvas, document):
        """Метод, которым рисуем две абсолютно
        спозиционированыые полоски для подписей"""
        canvas.setLineWidth(0.5)
        canvas.line(75*mm, 88*mm, 198*mm, 88*mm)
        canvas.line(75*mm, 25*mm, 198*mm, 25*mm)

    # Добавляем шаблон страницы с тремя областями
    doc.addPageTemplates([
        PageTemplate(
            id='TwoCol',
            frames=[frame_head, frame_body, frame_signature],
            onPage=on_page
        ),
    ])

    def ps(**kwargs):
        params = {
            'name': 'xxx',
            'fontName': 'DejaVuSerif',
            'fontSize': 11,
            'leading': 7*mm,
        }
        params.update(kwargs)
        return ParagraphStyle(**params)

    story = []

    def p(text, p_style=ps()):
        story.append(Paragraph(text, p_style))

    first = True

    for data in gaps_data:
        if not first:
            story.append(PageBreak())

        # Наполняем страницу мясом
        for _p in data['head'].split('\n'):
            p(_p)
        p('от %(name_genitive)s' % data)
        story.append(FrameBreak())
        p('ЗАЯВЛЕНИЕ', ps(alignment=TA_CENTER, fontSize=14))
        story.append(Spacer(1, 10*mm))
        p(
            '%(body_start)s c %(day_from)s по %(day_to)s%(body_end)s'
            % data, ps(firstLineIndent=10*mm)
        )
        story.append(FrameBreak())
        p('%(today)s' % data, ps(leading=0))
        p('/%(name_nominative)s/' % data, ps(alignment=TA_RIGHT))
        p('подпись', ps(alignment=TA_CENTER, fontSize=10, firstLineIndent=-18*mm))
        story.append(Spacer(1, 25*mm))
        p('СОГЛАСОВАНО:')
        story.append(Spacer(1, 10*mm))
        p('Руководитель')
        p('структурного подразделения:', ps(leading=0))
        p('/', ps(firstLineIndent=25*mm, leading=0, alignment=TA_CENTER))
        p('/', ps(alignment=TA_RIGHT))
        p('подпись', ps(alignment=TA_CENTER, fontSize=10, firstLineIndent=-18*mm))

        first = False

    # Записываем в файлик pdf
    doc.build(story)
    return file_object


def get_persons_names(person_ids):
    inflector = get_ids_repository(
        'inflector',
        'inflector',
        user_agent=settings.STAFF_USER_AGENT,
    )
    patern = '%(last_name)s %(first_name)s %(middle_name)s'

    persons = Staff.objects.values(
        'id',
        'first_name',
        'last_name',
        'middle_name',
        'gender',
        'extra__id',
        'extra__oebs_first_name',
        'extra__oebs_last_name',
        'extra__oebs_middle_name',
    ).filter(id__in=person_ids)

    result = {}

    for person in persons:
        extra = extract_related(person, 'extra')
        if extra['id'] is not None:
            person['first_name'] = extra['oebs_first_name']
            person['last_name'] = extra['oebs_last_name']
            person['middle_name'] = extra['oebs_middle_name']
        person['gender'] = person['gender'].lower()

        nominative = patern % person
        try:
            genitive = patern % inflector.inflect_person(person, 'родительный')
        except Exception:
            genitive = nominative

        result[person['id']] = nominative, genitive

    return result


def gaps_data_gen(template, gaps_data):
    with override('ru'):
        persons_names = get_persons_names(g['person_id'] for g in gaps_data)
        today = date_format(date.today())

        for gap_data in gaps_data:
            nominative, genitive = persons_names[gap_data['person_id']]

            yield {
                'head': template['head'],
                'name_genitive': genitive,
                'body_start': template['body_start'],
                'day_from': date_format(gap_data['date_from']),
                'day_to': date_format(gap_data['date_to']),
                'body_end': template['body_end'],
                'today': today,
                'name_nominative': nominative,
            }


def generate_vacations_pdf(file_object, template, gaps_data):
    return gen_pdf(file_object, gaps_data_gen(template, gaps_data))
