"""This module contains the implementation of a mock railroad server for
testing purposes.

The server will deliver pre-defined results for all requests sent to it.
It will not implement the full range of WebDAV requests.
"""

import sys
import os
import BaseHTTPServer

###

LOG = None

###

class _handler ( BaseHTTPServer.BaseHTTPRequestHandler):
    """Simple handler implementation for the mock server.
    """

    fake_path = '/repo/image/jpeg/000/xxx.jpg'
    fake_uuid = 'f280a956-0c87-11d9-a3a4-00d0b7e8a31c'

    fake_data = 'X'*1000

    fake_find_unowned_response = '''<?xml version="1.0" encoding="utf-8"?>
<search-result xmlns="http://www.infrae.com/namespaces/search">
  <request>/rrr/service/search/find_unowned</request>
  <size>1</size>
  <resources>

    <resource>
      <url>/rrr/repo/image/jpeg/000/XXX.jpg</url>
      <mime-type>image/jpeg</mime-type>
      <size>666</size>
      <lastmodified>2005-02-03 14:24:41+01</lastmodified>
    </resource>

  </resources>
</search-result>'''

    _propfind_response = '''<?xml version="1.0" encoding="utf-8"?>
<D:multistatus xmlns:D="DAV:">
<D:response xmlns:lp1="DAV:" xmlns:lp2="http://apache.org/dav/props/">
<D:href>%(path)s</D:href>
<D:propstat>
<D:prop>
<lp1:resourcetype><D:collection/></lp1:resourcetype>
<lp1:creationdate>2004-08-24T12:19:25Z</lp1:creationdate>
<lp1:getlastmodified>Tue, 24 Aug 2004 12:19:25 GMT</lp1:getlastmodified>
<lp1:getetag>"bbb47-1000-60476d40"</lp1:getetag>
<D:supportedlock>
<D:lockentry>
<D:lockscope><D:exclusive/></D:lockscope>
<D:locktype><D:write/></D:locktype>
</D:lockentry>
<D:lockentry>
<D:lockscope><D:shared/></D:lockscope>
<D:locktype><D:write/></D:locktype>
</D:lockentry>
</D:supportedlock>
<D:lockdiscovery/>
<D:getcontenttype>httpd/unix-directory</D:getcontenttype>
</D:prop>
<D:status>HTTP/1.1 200 OK</D:status>
</D:propstat>
</D:response>
<D:response xmlns:lp1="DAV:" xmlns:lp2="http://apache.org/dav/props/">
<D:href>%(path)s/image/</D:href>
<D:propstat>
<D:prop>
<lp1:resourcetype><D:collection/></lp1:resourcetype>
<lp1:creationdate>2004-08-24T12:18:49Z</lp1:creationdate>
<lp1:getlastmodified>Tue, 24 Aug 2004 12:18:49 GMT</lp1:getlastmodified>
<lp1:getetag>"4fdd3-1000-5e221c40"</lp1:getetag>
<D:supportedlock>
<D:lockentry>
<D:lockscope><D:exclusive/></D:lockscope>
<D:locktype><D:write/></D:locktype>
</D:lockentry>
<D:lockentry>
<D:lockscope><D:shared/></D:lockscope>
<D:locktype><D:write/></D:locktype>
</D:lockentry>
</D:supportedlock>
<D:lockdiscovery/>
<D:getcontenttype>httpd/unix-directory</D:getcontenttype>
</D:prop>
<D:status>HTTP/1.1 200 OK</D:status>
</D:propstat>
</D:response>
</D:multistatus>'''

    def do_GET ( self ):
        print >>LOG, 'MOCKSERVER: %s: %s %s' % (repr(self.client_address), self.command, self.path)
        path = self.path
        if path == self.fake_path:
            rdata = self.fake_data
            size = len(rdata)
        elif path == '/service/uuid/':
            # create and return fake uuid
            rdata = self.fake_uuid
            size = len(rdata)
        elif path == '/service/search/find_unowned':
            # create and return fake search result
            rdata = self.fake_find_unowned_response
            size = len(rdata)
        else:
            size = 0
            rdata = ''
        self.send_response(200, len(rdata))
        self.end_headers()
        if rdata:
            self.wfile.write(rdata)
        self.wfile.close()
        return

    def do_PROPFIND ( self ):
        """Handle PROPFIND request.
        """
        print >>LOG, 'MOCKSERVER: %s: %s %s' % (repr(self.client_address), self.command, self.path)
        LOG.flush()
        cl = self.headers.get('Content-Length', '0')        
        cl = int(cl)
        if cl > 0:
            recv = self.rfile.read(cl)
            print >>LOG, '  recv:', recv
        path = self.path
        if path in ('/', self.fake_path):
            res = self._propfind_response % locals()
            l = len(res)
            self.send_response(207, l)
            self.end_headers()
            self.wfile.write(res)
            self.wfile.close()
        else:
            self.send_error(404)
            self.wfile.close()
        return

    def do_POST ( self ):
        pass

    def do_OPTIONS ( self ):
        pass

    def log_message(self, format, *args):
        LOG.write("%s - - [%s] %s\n" %
                  (self.address_string(),
                   self.log_date_time_string(),
                   format%args))
        LOG.flush()
        return
#

class MockServer:
    """The mock server class used for testing.
    """

    def __init__ ( self ):
        self._host = 'localhost'
        self._port = 32080
        addr = (self._host, self._port)
        self._base_url = 'http://%s:%d/' % addr
        return

    def base_url ( self ):
        return self._base_url

    def start ( self ):
        """Start the server in a new process and return the PID of the
        server process.
        """
        # fork server process
        pid = os.fork()
        if not pid:
            # we're the child
            # create/open log file
            global LOG
            LOG = file('./mockserver.log', 'wb')
            # start server
            addr = (self._host, self._port)
            self._server = BaseHTTPServer.HTTPServer(addr, _handler)
            self._server.serve_forever()
            sys.exit()
        if pid > 0:
            # we're the parent
            return pid
        else:
            # shit happens... on a daily basis...
            raise OSError, (pid,)
        return
#
###

## if __name__ == '__main__':
##     server = MockServer()
##     server.start()
