import OFS
import re

from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText
from zope.component import queryUtility
from zope.component import getMultiAdapter
from Acquisition import aq_inner
#from zope.interface import implements

from Products.CMFCore.interfaces import ISiteRoot
from Products.CMFCore.utils import getToolByName
from Products.Five.browser import BrowserView
from Products.statusmessages.interfaces import IStatusMessage

from Products.EasyNewsletter.interfaces import IENLRegistrationTool
from Products.EasyNewsletter.config import MESSAGE_CODE
from Products.EasyNewsletter import EasyNewsletterMessageFactory as _


class SubscriberView(BrowserView):
    """
    """
    
    def portal_state(self):
        context = aq_inner(self.context)
        return getMultiAdapter((context, self.request), name=u'plone_portal_state')

    @property
    def portal(self):
        pstate = self.portal_state()
        return pstate.portal()

    @property
    def portal_url(self):
        pstate = self.portal_state()
        return pstate.portal_url()

    def register_subscriber(self):
        """
        """
        subscriber = self.request.get("subscriber")
        fullname = self.request.get("fullname", "")
        organization = self.request.get("organization", "")
        path_to_easynewsletter = self.request.get("newsletter")
        # remove leading slash from paths like: /mynewsletter
        path_to_easynewsletter = path_to_easynewsletter.strip('/')
        newsletter_container = self.portal.restrictedTraverse(path_to_easynewsletter)
        messages = IStatusMessage(self.request)
        if not subscriber:
            messages.addStatusMessage(_("Please enter a valid e-mail address."), "error")
            return self.request.response.redirect(newsletter_container.absolute_url())
        from Products.validation.validators.BaseValidators import EMAIL_RE
        EMAIL_RE = "^" + EMAIL_RE
        mo = re.search(EMAIL_RE, subscriber)
        if not mo: 
            messages.addStatusMessage(_("Please enter a valid e-mail address."), "error")
            return self.request.response.redirect(newsletter_container.absolute_url())
        if subscriber in newsletter_container.objectIds(): 
            messages.addStatusMessage(_("Your e-mail address is already registered."), "error")
            return self.request.response.redirect(newsletter_container.absolute_url())
        subscriber_data = {}
        subscriber_data["subscriber"] = subscriber
        subscriber_data["fullname"] = fullname
        subscriber_data["organization"] = organization
        subscriber_data["path_to_easynewsletter"] = path_to_easynewsletter

        # use password reset tool to create a hash
        pwr_data = self._requestReset(subscriber)
        hashkey = pwr_data['randomstring']
        enl_registration_tool = queryUtility(IENLRegistrationTool,'enl_registration_tool')
        if hashkey not in enl_registration_tool.objectIds():
            enl_registration_tool[hashkey] = RegistrationData(hashkey, **subscriber_data)
            msg_subject = newsletter_container.getRawSubscriber_confirmation_mail_subject().replace(
                "${portal_url}", self.portal_url.strip('http://')
            )
            confirmation_url = self.portal_url + '/confirm-subscriber?hkey=' + str(hashkey)
            msg_text = newsletter_container.getRawSubscriber_confirmation_mail_text().replace("${newsletter_title}", newsletter_container.Title())
            msg_text = msg_text.replace("${subscriber_email}", subscriber)
            msg_text = msg_text.replace("${confirmation_url}", confirmation_url)
            msg_sender = self.portal.getProperty('email_from_address')
            msg_receiver = subscriber 
            msg = MIMEText(msg_text)
            msg['To']= msg_receiver
            msg['From'] = msg_sender
            msg['Subject'] = msg_subject
            #msg.epilogue   = ''
            self.portal.MailHost.send(msg.as_string())
            messages.addStatusMessage(_("Your email has been registered. A confirmation email was sent to your address. Please check your inbox and click on the link in the email in order to confirm your subscription."), "info")
        self.request.response.redirect(newsletter_container.absolute_url())

    def confirm_subscriber(self):
        hashkey = self.request.get('hkey')
        enl_registration_tool = queryUtility(IENLRegistrationTool,'enl_registration_tool')
        regdataobj = enl_registration_tool.get(hashkey)
        messages = IStatusMessage(self.request)
        if regdataobj:
            easynewsletter = self.portal.restrictedTraverse(regdataobj.path_to_easynewsletter)
            valid_email, error_code = easynewsletter.addSubscriber(regdataobj.subscriber, regdataobj.fullname, regdataobj.organization)
            if valid_email:
                # now delete the regobj
                del enl_registration_tool[hashkey]
                messages.addStatusMessage(MESSAGE_CODE[error_code])
            else:
                messages.addStatusMessage(MESSAGE_CODE[error_code], "error")
        else:
            messages.addStatusMessage(_("Please enter a valid e-mail address."), "error")
        return self.request.response.redirect(easynewsletter.absolute_url())


    def _requestReset(self, userid):
        """Ask the system to start the password reset procedure for
        user 'userid'.

        Returns a dictionary with the random string that must be
        used to reset the password in 'randomstring', the expiration date
        as a DateTime in 'expires', and the userid (for convenience) in
        'userid'.
        ### taken from Products.PasswordResetTool and but without getValidUser check!
        """
        pwrtool = getToolByName(self.context, 'portal_password_reset')
        randomstring = pwrtool.uniqueString(userid)
        expiry = pwrtool.expirationDate()
        pwrtool._requests[randomstring] = (userid, expiry)
        pwrtool.clearExpired(10)   # clear out untouched records more than 10 days old
                                # this is a cheap sort of "automatic" clearing
        pwrtool._p_changed = 1
        retval = {}
        retval['randomstring'] = randomstring
        retval['expires'] = expiry
        retval['userid'] = userid
        return retval


class RegistrationData(OFS.SimpleItem.SimpleItem):
    """ holds data from OnlineMemberSignupForm
    """

    def __init__(self, id, **kw):
        self.id = id
        for key, value in kw.items():
            setattr(self, key, value)
        super(RegistrationData, self).__init__(id)

    @property
    def title(self):
        return "%s - %s" % (self.fullname, self.subscriber)
