"""Resources

This module contains a handler class for resources.
"""

import binascii
import gzip
import hashlib
import mimetypes
import os
import re
import StringIO
import urlparse

from config import config
import encodings
import regexes as r


class FileExistError(Exception):
    """Exception which is raised when file does not exist"""
    pass


class FileAccessError(Exception):
    """Exception which is raised when file exists, but cannot be accessed"""
    pass


class Resource:
    """Class for representing a Resource (file)"""

    def __init__(self, uri):
        """Initialize the resource"

        Raises:
            FileExistError: if resource does not exist
            FileAccessError: if resource exists, but cannot be accessed

        Args:
            uri (str): Uniform Resource Identifier
        """
        if uri == None:
            raise FileExistError
        self.uri = uri
        out = urlparse.urlparse(uri)
        self.path = os.path.join(config('root', default='content'), 
                out.path.lstrip("/"))
        if not os.path.exists(self.path):
            raise FileExistError
        if os.path.isdir(self.path):
            self.path = os.path.join(self.path, 
                    config('index', default='index.html'))
            if not os.path.exists(self.path):
                raise FileAccessError
        if not os.path.isfile(self.path):
            raise FileExistError
        if not os.access(self.path, os.R_OK):
            raise FileAccessError

    def generate_etag(self):
        """Generate the ETag for the resource

        Returns:
            str: ETag for the resource
        """
        stat = os.stat(self.path)
        m = hashlib.md5()
        m.update(str(stat))
        etag = binascii.hexlify(m.digest())
        return etag

    def etag_match(self, etag):
        if etag == None:
            return False
        my_etag = self.generate_etag()
        return etag == '*' or \
                any([tag == my_etag for tag in re.split(r.ETagSplit, etag)])

    def get_content(self, encoding=encodings.IDENTITY):
        """Get the contents of the resource
        
        Returns:
            str: Contents of the resource
        """
        content = open(self.path).read()
        return encodings.encode(encoding, content)

    def get_content_type(self):
        """Get the content type, i.e "text/html"

        Returns:
            str: type of content in the resource
        """
        mimetype = mimetypes.guess_type(self.path)
        return mimetype[0]

    def get_content_encoding(self):
        """Get the content encoding, i.e "gzip"

        Returns:
            str: encoding used for the resource
        """
        mimetype = mimetypes.guess_type(self.path)
        return mimetype[1]

    def get_content_length(self):
        """Get the length of the resource

        Returns:
            int: length of resource in bytes
        """
        return os.path.getsize(self.path)