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

################################################################
# xmldirector.plonecore
# (C) 2016,  Andreas Jung, www.zopyx.com, Tuebingen, Germany
################################################################

import mimetypes
import lxml.html

from zope.interface import implements
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
from ZPublisher.Iterators import IStreamIterator

from .view_registry import precondition_registry
from .view_registry import Precondition
from . import config


class connector_iterator(file):

    implements(IStreamIterator)

    def __init__(self, handle, mode='rb', streamsize=1 << 16):
        self.fp = handle.open(handle.leaf_filename, mode)
        self.streamsize = streamsize

    def next(self):
        data = self.fp.read(self.streamsize)
        if not data:
            raise StopIteration
        return data

    def __len__(self):
        cur_pos = self.fp.tell()
        self.fp.seek(0, 2)
        size = self.fp.tell()
        self.seek(cur_pos, 0)
        return size


# Default view  for connector

def default_html_handler(get_handle, filename, view_name, request):

    html_template = ViewPageTemplateFile('html_view.pt')

    # exist-db base url
    base_url = '{}/@@view/{}'.format(
        request.context.absolute_url(1),
        '/'.join(request.subpath[:-1]))
    # get HTML
    html = get_handle.open(get_handle.leaf_filename, 'rb').read()
    html = unicode(html, 'utf8')
    if html.startswith(u'<?xml'):
        pos = html.find('?>')
        html = html[pos+3:]
    root = lxml.html.fromstring(html)

    # rewrite relative image urls
    for img in root.xpath('//img'):
        src = img.attrib['src']
        if not src.startswith('http'):
            img.attrib['src'] = '{}/{}'.format(base_url, src)

    # rewrite relative image urls
    for link in root.xpath('//link'):
        src = link.attrib['href']
        if not src.startswith('http'):
            link.attrib['href'] = '{}/{}'.format(base_url, src)

    html = lxml.html.tostring(root, encoding=unicode)

    return html_template.pt_render(dict(
        template='html_view',
        request=request,
        context=request.context,
        options=dict(
            base_url=base_url,
            html=html)))


def ace_editor(get_handle, filename, view_name, request,
               readonly=False, template_name='ace_editor.pt'):
    """ Default handler for showing/editing textish content through the ACE editor """

    mt, encoding = mimetypes.guess_type(filename)
    content = get_handle.open(get_handle.leaf_filename, 'rb').read()
    ace_mode = config.ACE_MODES.get(mt, 'text')
    template = ViewPageTemplateFile(template_name)
    action_url = '{}/view-editor/{}'.format(request.context.absolute_url(),
                                            '/'.join(request.subpath))
    view_url = '{}/view-editor-readonly/{}'.format(request.context.absolute_url(),
                                                   '/'.join(request.subpath))
    return template.pt_render(dict(
        template='ace_editor.pt',
        request=request,
        context=request.context,
        options=dict(content=content,
                     action_url=action_url,
                     view_url=view_url,
                     readonly=readonly,
                     ace_readonly=str(readonly).lower(),  # JS
                     ace_mode=ace_mode)))


def ace_editor_readonly(get_handle, filename, view_name,
                        request, readonly=True, template_name='ace_editor.pt'):
    return ace_editor(
        get_handle, filename, view_name, request, readonly, template_name)


def default_view_handler(get_handle, filename, view_name, request):
    """ Default handler for images and other binary resources """

    info = get_handle.getinfo(get_handle.leaf_filename)
    mt, encoding = mimetypes.guess_type(filename)
    if not mt:
        mt = 'application/octet-stream'
    request.response.setHeader('Content-Type', mt)
    if 'filename' in request:
        request.response.setHeader(
            'Content-Disposition', 'attachment;filename={}'.format(request['filename']))
    if 'size' in info:
        request.response.setHeader('Content-Length', info['size'])
        return connector_iterator(get_handle)
    else:
        data = get_handle.open(get_handle.leaf_filename, 'rb').read()
        request.response.setHeader('Content-Length', len(data))
        return data


precondition_registry.register(Precondition(suffixes=['.html', '.htm'],
                                            view_names=['view'],
                                            view_handler=default_html_handler))
precondition_registry.register(Precondition(suffixes=['.xml', '.html', '.htm', '.css', '.json'],
                                            view_names=['view-editor'],
                                            view_handler=ace_editor))
precondition_registry.register(Precondition(suffixes=['.xml', '.html', '.htm', '.css', '.json'],
                                            view_names=[
                                                'view-editor-readonly'],
                                            view_handler=ace_editor_readonly))
precondition_registry.set_default(
    Precondition(view_handler=default_view_handler))
