# -*- coding: UTF-8 -*-
# -*- Mode: Python; py-indent-offset: 4 -*-
# Authors: Nik Kim <fafhrd@datacom.kz> 

import traceback
from smtpd import SMTPChannel
from StringIO import StringIO
import sys, os, errno, time, socket, asyncore

from ZServer.PubCore import handle
from ZPublisher.BaseRequest import BaseRequest
from ZPublisher.BaseResponse import BaseResponse

class SMTPServer(asyncore.dispatcher):
    def __init__(self, ip, port, module):
        asyncore.dispatcher.__init__(self)
        self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
        self.set_reuse_addr()
        self.bind((ip,port))
        self.listen(5)
        self.module = module
        
        if ip=='':
            addr = 'any'
        else:
            addr = ip

        self.log_info('SMTP server started\n\tAddress: %s\n\tPort: %s'%(addr, port))

    def handle_accept(self):
        conn, addr = self.accept()
        self.log_info('Incoming connection from %s' % repr(addr))
        channel = SMTPChannel(self, conn, addr)

    def process_message(self, peer, mailfrom, rcpttos, data):
        """ forward email to /Control_panel/smtp_service/process_message
            beware! process async
        """
        
        try:
            err = StringIO()
            out = StringIO()

            response=SMTPResponse(stdout=out, stderr=err)
            
            request=SMTPRequest(response, peer, mailfrom, rcpttos, data)
            handle(self.module, request, response)
        except Exception, e:
            return '421 %s' % e


class SMTPResponse(BaseResponse):

    def _finish(self):
        pass
    
    pass


_marker = []
class SMTPRequest(BaseRequest):

    args = ()
    common = {}
    environ = {}

    def __init__(self, response, peer, from_addr, to_addrs, data):
        self.response = response
        BaseRequest.__init__(
            self, peer=peer, from_addr=from_addr, to_addrs=to_addrs, data=data)

    def traverse(self, path, response=None, validated_hook=None):
        request=self
        request_get=request.get
        if response is None: response=self.response
        debug_mode=response.debug_mode

        parents=request['PARENTS']
        object=parents[-1]
        del parents[:]

        entry_name = 'Control_Panel'

        subobject=object.__bobo_traverse__(request,entry_name)
        if type(subobject) is type(()) and len(subobject) > 1:
            parents[-1:] = list(subobject[:-1])
            object, subobject = subobject[-2:]
        
        return subobject.smtp_service.process_message

    def get(self, key, default=None):
        if key=='REQUEST': return self

        if key=='RESPONSE': return self.response

        if key == 'PATH_INFO': return '/Control_Panel/smtp_service'

        v=self.other.get(key, _marker)
        if v is not _marker: return v
        v=self.common.get(key, default)
        if v is not _marker: return v
   
        return default
