from quixote import get_request, get_response, get_session, redirect
from quixote.directory import Directory, AccessControlled
from quixote.html import htmltext, TemplateIO

import wcs

from wcs.qommon import _
from wcs.qommon.backoffice.menu import html_top
from wcs.qommon.admin.menu import command_icon
from wcs.qommon import get_cfg
from wcs.qommon import errors
from wcs.qommon.form import *
from wcs.qommon.afterjobs import AfterJob

from .announces import Announce, AnnounceSubscription


class SubscriptionDirectory(Directory):
    _q_exports = ['delete_email', "delete_sms"]

    def __init__(self, subscription):
        self.subscription = subscription

    def delete_email(self):
        form = Form(enctype='multipart/form-data')
        form.widgets.append(HtmlWidget('<p>%s</p>' % _(
                        'You are about to delete this subscription.')))
        form.add_submit('submit', _('Submit'))
        form.add_submit('cancel', _('Cancel'))
        if form.get_submit() == 'cancel':
            return redirect('..')
        if not form.is_submitted() or form.has_errors():
            get_response().breadcrumb.append(('delete', _('Delete')))
            html_top('announces', title = _('Delete Subscription'))
            r = TemplateIO(html=True)
            r += htmltext('<h2>%s</h2>') % _('Deleting Subscription')
            r += form.render()
            return r.getvalue()
        else:
            self.subscription.remove("email")
            return redirect('..')

    def delete_sms(self):
        form = Form(enctype='multipart/form-data')
        form.widgets.append(HtmlWidget('<p>%s</p>' % _(
                        'You are about to delete this subscription.')))
        form.add_submit('submit', _('Submit'))
        form.add_submit('cancel', _('Cancel'))
        if form.get_submit() == 'cancel':
            return redirect('..')
        if not form.is_submitted() or form.has_errors():
            get_response().breadcrumb.append(('delete', _('Delete')))
            html_top('announces', title = _('Delete Subscription'))
            r = TemplateIO(html=True)
            r += htmltext('<h2>%s</h2>') % _('Deleting Subscription')
            r += form.render()
            return r.getvalue()
        else:
            self.subscription.remove("sms")
            return redirect('..')


class SubscriptionsDirectory(Directory):
    _q_exports = ['']

    def _q_traverse(self, path):
        get_response().breadcrumb.append(('subscriptions', _('Subscriptions')))
        return Directory._q_traverse(self, path)

    def _q_index(self):
        html_top('announces', _('Announces Subscribers'))
        r = TemplateIO(html=True)

        r += htmltext('<h2>%s</h2>') % _('Announces Subscribers')

        subscribers = AnnounceSubscription.select()
        r += htmltext('<ul class="biglist" id="subscribers-list">')
        for l in subscribers:
            if l.email:
                if l.enabled is False:
                    r += htmltext('<li class="disabled">')
                else:
                    r += htmltext('<li>')
                r += htmltext('<strong class="label">')
                if l.user:
                    r += l.user.display_name
                elif l.email:
                    r += l.email
                r += htmltext('</strong>')
                r += htmltext('<p class="details">')
                if l.user:
                    r += l.user.email
                r += htmltext('</p>')
                r += htmltext('<p class="commands">')
                r += command_icon('%s/delete_email' % l.id, 'remove', popup = True)
                r += htmltext('</p></li>')
                r += htmltext('</li>')
            if l.sms:
                if l.enabled_sms is False:
                    r += htmltext('<li class="disabled">')
                else:
                    r += htmltext('<li>')
                r += htmltext('<strong class="label">')
                if l.user:
                    r += l.user.display_name
                elif l.email:
                    r += l.email
                r += htmltext('</strong>')
                r += htmltext('<p class="details">')
                r += l.sms
                r += htmltext('</p>')
                r += htmltext('<p class="commands">')
                r += command_icon('%s/delete_sms' % l.id, 'remove', popup = True)
                r += htmltext('</p></li>')
                r += htmltext('</li>')
        r += htmltext('</ul>')
        return r.getvalue()

    def _q_lookup(self, component):
        try:
            sub = AnnounceSubscription.get(component)
        except KeyError:
            raise errors.TraversalError()
        get_response().breadcrumb.append((str(sub.id), str(sub.id)))
        return SubscriptionDirectory(sub)

    def listing(self):
        return redirect('.')

class AnnounceDirectory(Directory):
    _q_exports = ['', 'edit', 'delete', 'email', 'sms']

    def __init__(self, announce):
        self.announce = announce

    def _q_index(self):
        form = Form(enctype='multipart/form-data')
        get_response().filter['sidebar'] = self.get_sidebar()

        if self.announce.sent_by_email_time is None:
            form.add_submit('email', _('Send email'))

        announces_cfg = get_cfg('announces', {})
        if announces_cfg.get('sms_support', 0) and self.announce.sent_by_sms_time is None:
            form.add_submit('sms', _('Send SMS'))

        if form.get_submit() == 'edit':
            return redirect('edit')
        if form.get_submit() == 'delete':
            return redirect('delete')
        if form.get_submit() == 'email':
            return redirect('email')
        if form.get_submit() == 'sms':
            return redirect('sms')

        html_top('announces', title = _('Announce: %s') % self.announce.title)
        r = TemplateIO(html=True)
        r += htmltext('<h2>%s</h2>') % _('Announce: %s') % self.announce.title
        r += htmltext('<div class="bo-block">')
        r += htmltext('<p>')
        r += self.announce.text
        r += htmltext('</p>')
        r += htmltext('</div>')

        if form.get_submit_widgets():
            r += form.render()

        return r.getvalue()

    def get_sidebar(self):
        r = TemplateIO(html=True)
        r += htmltext('<ul>')
        r += htmltext('<li><a href="edit">%s</a></li>') % _('Edit')
        r += htmltext('<li><a href="delete">%s</a></li>') % _('Delete')
        r += htmltext('</ul>')
        return r.getvalue()

    def email(self):
        if get_request().form.get('job'):
            try:
                job = AfterJob.get(get_request().form.get('job'))
            except KeyError:
                return redirect('..')
            html_top('announces', title = _('Announce: %s') % self.announce.title)
            r = TemplateIO(html=True)
            get_response().add_javascript(['jquery.js', 'afterjob.js'])
            r += htmltext('<dl class="job-status">')
            r += htmltext('<dt>')
            r += _(job.label)
            r += htmltext('</dt>')
            r += htmltext('<dd>')
            r += htmltext('<span class="afterjob" id="%s">') % job.id
            r += _(job.status)
            r += htmltext('</span>')
            r += htmltext('</dd>')
            r += htmltext('</dl>')

            r += htmltext('<div class="done">')
            r += htmltext('<a href="../">%s</a>') % _('Back')
            r += htmltext('</div>')

            return r.getvalue()
        else:
            job = get_response().add_after_job(
                    str(N_('Sending emails for announce')),
                    self.announce.email)
            return redirect('email?job=%s' % job.id)

    def sms(self):
        if get_request().form.get('job'):
            try:
                job = AfterJob.get(get_request().form.get('job'))
            except KeyError:
                return redirect('..')
            html_top('announces', title = _('Announce: %s') % self.announce.title)
            get_response().add_javascript(['jquery.js', 'afterjob.js'])
            r = TemplateIO(html=True)
            r += htmltext('<dl class="job-status">')
            r += htmltext('<dt>')
            r += _(job.label)
            r += htmltext('</dt>')
            r += htmltext('<dd>')
            r += htmltext('<span class="afterjob" id="%s">') % job.id
            r += _(job.status)
            r += htmltext('</span>')
            r += htmltext('</dd>')
            r += htmltext('</dl>')

            r += htmltext('<div class="done">')
            r += htmltext('<a href="../">%s</a>') % _('Back')
            r += htmltext('</div>')

            return r.getvalue()
        else:
            job = get_response().add_after_job(
                    str(N_('Sending sms for announce')),
                    self.announce.sms)
            return redirect('sms?job=%s' % job.id)

    def edit(self):
        form = self.form()
        if form.get_submit() == 'cancel':
            return redirect('.')

        if form.is_submitted() and not form.has_errors():
            self.submit(form)
            return redirect('..')

        html_top('announces', title = _('Edit Announce: %s') % self.announce.title)
        r = TemplateIO(html=True)
        r += htmltext('<h2>%s</h2>') % _('Edit Announce: %s') % self.announce.title
        r += form.render()
        return r.getvalue()

    def form(self):
        form = Form(enctype='multipart/form-data')
        form.add(StringWidget, 'title', title = _('Title'), required = True,
                value = self.announce.title)
        if self.announce.publication_time:
            pub_time = time.strftime(misc.date_format(), self.announce.publication_time)
        else:
            pub_time = None
        form.add(DateWidget, 'publication_time', title = _('Publication Time'),
                value = pub_time)
        if self.announce.expiration_time:
            exp_time = time.strftime(misc.date_format(), self.announce.expiration_time)
        else:
            exp_time = None
        form.add(DateWidget, 'expiration_time', title = _('Expiration Time'),
                value = exp_time)
        form.add(TextWidget, 'text', title = _('Text'), required = True,
                value = self.announce.text, rows = 10, cols = 70)
        if get_cfg('misc', {}).get('announce_themes'):
            form.add(SingleSelectWidget, 'theme', title = _('Announce Theme'),
                    value = self.announce.theme,
                    options = get_cfg('misc', {}).get('announce_themes'))
        form.add(CheckboxWidget, 'hidden', title = _('Hidden'),
                value = self.announce.hidden)
        form.add_submit('submit', _('Submit'))
        form.add_submit('cancel', _('Cancel'))
        return form

    def submit(self, form):
        for k in ('title', 'text', 'hidden', 'theme'):
            widget = form.get_widget(k)
            if widget:
                setattr(self.announce, k, widget.parse())
        for k in ('publication_time', 'expiration_time'):
            widget = form.get_widget(k)
            if widget:
                wid_time = widget.parse()
                if wid_time:
                    setattr(self.announce, k, time.strptime(wid_time, misc.date_format()))
                else:
                    setattr(self.announce, k, None)
        self.announce.store()

    def delete(self):
        form = Form(enctype='multipart/form-data')
        form.widgets.append(HtmlWidget('<p>%s</p>' % _(
                        'You are about to irrevocably delete this announce.')))
        form.add_submit('submit', _('Submit'))
        form.add_submit('cancel', _('Cancel'))
        if form.get_submit() == 'cancel':
            return redirect('..')
        if not form.is_submitted() or form.has_errors():
            get_response().breadcrumb.append(('delete', _('Delete')))
            html_top('announces', title = _('Delete Announce'))
            r = TemplateIO(html=True)
            r += htmltext('<h2>%s</h2>') % _('Deleting Announce: %s') % self.announce.title
            r += form.render()
            return r.getvalue()
        else:
            self.announce.remove_self()
            return redirect('..')


class AnnouncesDirectory(AccessControlled, Directory):
    _q_exports = ['', 'new', 'listing', 'subscriptions', 'update_order', 'log']
    label = N_('Announces')

    subscriptions = SubscriptionsDirectory()

    def is_accessible(self, user):
        from .backoffice import check_visibility
        return check_visibility('announces', user)

    def _q_access(self):
        user = get_request().user
        if not user:
            raise errors.AccessUnauthorizedError()

        if not self.is_accessible(user):
            raise errors.AccessForbiddenError(
                    public_msg = _('You are not allowed to access Announces Management'),
                    location_hint = 'backoffice')

        get_response().breadcrumb.append(('announces/', _('Announces')))

    def _q_index(self):
        html_top('announces', _('Announces'))
        r = TemplateIO(html=True)

        get_response().filter['sidebar'] = self.get_sidebar()

        announces = Announce.select()
        announces.sort(lambda x,y: cmp(x.publication_time or x.modification_time,
                    y.publication_time or y.modification_time))
        announces.reverse()

        r += htmltext('<ul class="biglist" id="announces-list">')
        for l in announces:
            announce_id = l.id
            if l.hidden:
                r += htmltext('<li class="disabled" class="biglistitem" id="itemId_%s">') % announce_id
            else:
                r += htmltext('<li class="biglistitem" id="itemId_%s">') % announce_id
            r += htmltext('<strong class="label"><a href="%s/">%s</a></strong>') % (l.id, l.title)
            if l.publication_time:
                r += htmltext('<p class="details">')
                r += time.strftime(misc.date_format(), l.publication_time)
                r += htmltext('</p>')
            r += htmltext('</li>')
        r += htmltext('</ul>')
        return r.getvalue()

    def get_sidebar(self):
        r = TemplateIO(html=True)
        r += htmltext('<ul id="sidebar-actions">')
        r += htmltext(' <li><a class="new-item" href="new">%s</a></li>') % _('New')
        r += htmltext(' <li><a href="subscriptions/">%s</a></li>') % _('Subscriptions')
        r += htmltext(' <li><a href="log">%s</a></li>') % _('Log')
        r += htmltext('</ul>')
        return r.getvalue()

    def log(self):
        announces = Announce.select()
        log = []
        for l in announces:
            if l.publication_time:
                log.append((l.publication_time, _('Publication'), l))
            if l.sent_by_email_time:
                log.append((l.sent_by_email_time, _('Email'), l))
            if l.sent_by_sms_time:
                log.append((l.sent_by_sms_time, _('SMS'), l))
        log.sort()

        get_response().breadcrumb.append(('log', _('Log')))
        html_top('announces', title = _('Log'))
        r = TemplateIO(html=True)

        r += htmltext('<table>')
        r += htmltext('<thead>')
        r += htmltext('<tr>')
        r += htmltext('<th>%s</th>') % _('Time')
        r += htmltext('<th>%s</th>') % _('Type')
        r += htmltext('<td></td>')
        r += htmltext('</tr>')
        r += htmltext('</thead>')
        r += htmltext('<tbody>')
        for log_time, log_type, log_announce in log:
            r += htmltext('<tr>')
            r += htmltext('<td>')
            r += misc.localstrftime(log_time)
            r += htmltext('</td>')
            r += htmltext('<td>')
            r += log_type
            r += htmltext('</td>')
            r += htmltext('<td>')
            r += htmltext('<a href="%s">%s</a>') % (log_announce.id, log_announce.title)
            r += htmltext('</td>')
            r += htmltext('</tr>')
        r += htmltext('</tbody>')
        r += htmltext('</table>')
        return r.getvalue()

    def update_order(self):
        request = get_request()
        new_order = request.form['order'].strip(';').split(';')
        announces = Announce.select()
        dict = {}
        for l in announces:
            dict[str(l.id)] = l
        for i, o in enumerate(new_order):
            dict[o].position = i + 1
            dict[o].store()
        return 'ok'

    def new(self):
        announce = Announce()
        announce.publication_time = time.gmtime()
        announce_ui = AnnounceDirectory(announce)

        form = announce_ui.form()
        if form.get_submit() == 'cancel':
            return redirect('.')

        if form.is_submitted() and not form.has_errors():
            announce_ui.submit(form)
            return redirect('%s/' % announce_ui.announce.id)

        get_response().breadcrumb.append(('new', _('New Announce')))
        html_top('announces', title = _('New Announce'))
        r = TemplateIO(html=True)
        r += htmltext('<h2>%s</h2>') % _('New Announce')
        r += form.render()
        return r.getvalue()

    def _q_lookup(self, component):
        try:
            announce = Announce.get(component)
        except KeyError:
            raise errors.TraversalError()
        get_response().breadcrumb.append((str(announce.id), announce.title))
        return AnnounceDirectory(announce)

    def listing(self):
        return redirect('.')

