# Copyright (c) 2004 Infrae. All rights reserved.
# See also LICENSE.txt
# python
import urlparse
# pydavclient
import dav
# Railroad
from Products.Railroad import interfaces, errors, utils

class Proxy:
    """Bare Railroad proxy
    """
    
    __implements__ = (interfaces.IRailroadProxy,)
    
    _resource_path = None
    _railroad_service_path = None
    
    def __init__(self, unique_id):
        self._unique_id = unique_id
    
    # ACCESSORS
    
    def unique_id(self):
        """Return the unique id of this proxy.
        """
        return self._unique_id

    def has_resource(self):
        """Return True if this proxy has a resource assigned, otherwise
        return False
        """
        return self.resource_path() and True or False
    
    def is_associated_to_service(self):
        """Return True if this proxy has been associated to a 
        Railroad Service. Return False otherwise.
        """
        try:
            service = self.get_railroad_service()
            if service:
                return True
        except errors.ServiceNotFoundError, e:
            return False
    
    def get_railroad_service(self):
        """Return the railroad_service object used for this proxy.

        Raises ServiceNotFoundError when this proxy is not
        associated with a service.
        """
        if self._railroad_service_path is None:
            raise errors.ServiceNotFoundError()
        
        service = self.restrictedTraverse(self._railroad_service_path, None)
        if service is None:
            raise errors.ServiceNotFoundError()
        return service
    
    def resource_path(self):
        """The path portion of the URL of the resource on the 
        Railroad server.
        
        Return None if there is no resource associated with this proxy.        
        """
        return self._resource_path
        
    def resource_url(self):
        """Return the full URL of the resource this proxy refers to.
        
        Raises ProxyNotAssignedError if there is no resource assigned
        to this proxy.
        """
        service = self.get_railroad_service()
        url = service.resource_url_for(self)
        return url
    
    def fetch_properties(self):
        """Returns all properties as stored for the resource assigned
        to this proxy. Keys and values will be in unicode.
        
        Raises ProxyNotAssignedError if there is no resource assigned
        to this proxy.
        """
        service = self.get_railroad_service()
        properties = service.fetch_properties_for(self)
        return properties
    
    # MANIPULATORS

    def set_railroad_service(self, service):
        """Associate the resource to a railroad_service.
        """
        #try:
        #    prev_service = self.get_railroad_service()
        #    prev_service.unregister_proxy(self)
        #except errors.ServiceNotFoundError, e:
        #    pass
        
        self._railroad_service_path = service.getPhysicalPath()
        service = self.get_railroad_service()
        service.register_proxy(self)
    
    def set_resource_path(self, resource_path):
        """Assign a resource to this proxy.
        
        resource_path is the path portion of the URL of the resource on the
        Railroad server.
        """
        if resource_path.startswith('/'):
            raise errors.InvalidPathError('Resource path should be relative')
        self._resource_path = resource_path

    def set_properties(self, properties_dict):
        """Stores properties on the resource assigned to this proxy.
        
        Keys and values of the property_dict should be unicode.
        
        Raises ProxyNotAssignedError if there is no resource assigned
        to this proxy.
        """
        service = self.get_railroad_service()
        service.set_properties_for(self, properties_dict)

    # RAILROAD EVENTS
    
    def on_upload_succeeded(self, url, errormsg):
        """Notifies proxy of a succesful resource upload to the Railroad
        repository.
        
        Method should be publishable (i.e., the implementation needs
        to have a doc string).
        """
        # XXX maybe use urlparse ayway to get rid of potential
        # query segments in the url?
        service = self.get_railroad_service()
        repository_url = service.repository_url()
        if not url.startswith(repository_url):
            # Wow, something weird happening here!! The resource url *should*
            # start with the repository url, but apparently it doesn't...
            raise errors.RailroadError, ('Wrong start of resource URL!', url, repository_url)
        splits = url.split(repository_url)
        path = splits[1]
        self.set_resource_path(path)
    
    def on_upload_failed(self, errormsg):
        """Notifies proxy of a failed resource upload to the Railroad
        repository.
        
        Method should be publishable (i.e., the implementation needs
        to have a doc string).
        """
        pass
    
    # ZOPE EVENTS
    
    def on_create(self):
        """Should be called when this proxy was just created.
        """
        print 'on_create called for', self.getPhysicalPath()
        
    def on_paste(self):
        """Should be called just after this proxy has been cloned to its 
        destination.
        """
        print 'on_paste called for', self.getPhysicalPath()
    
    def on_delete(self):
        """Should be called just *before* this proxy is deleted.
        """
        service = self.get_railroad_service()
        service.unregister_proxy(self)
        # Delete resource on Railroad server
        user, pw = service.get_user_pw(self.REQUEST)
        url = self.resource_url()
        hostport, upath = urlparse.urlparse(url)[1:3]
        if ':' in hostport:
            host, port = hostport.split(":")
            port = int(port)
        else:
            host = hostport
            port = 80
        dc = dav.davbase.DAVConnection(host, port)
        dc.set_auth(user, pw)
        dc._realm = service.repository_name()
        dc.delete(upath)
        return
