import base64
import cgi
import Cookie
import StringIO
import tempfile
import urlparse

from . import stash
from .utils import HTTPException

missing = object()


class Server(object):
    """Data about the server environment

    .. attribute:: config

    Environment configuration information with information about the
    various servers running, their hostnames and ports.

    .. attribute:: stash

    Stash object holding state stored on the server between requests.

    """
    config = None

    def __init__(self, request):
        self._stash = None
        self._request = request

    @property
    def stash(self):
        if self._stash is None:
            address, authkey = stash.load_env_config()
            self._stash = stash.Stash(self._request.url_parts.path, address, authkey)
        return self._stash


class InputFile(object):
    max_buffer_size = 1024*1024

    def __init__(self, rfile, length):
        """File-like object used to provide a seekable view of request body data"""
        self._file = rfile
        self.length = length

        self._file_position = 0

        if length > self.max_buffer_size:
            self._buf = tempfile.TemporaryFile(mode="rw+b")
        else:
            self._buf = StringIO.StringIO()

    @property
    def _buf_position(self):
        rv = self._buf.tell()
        assert rv <= self._file_position
        return rv

    def read(self, bytes=-1):
        assert self._buf_position <= self._file_position

        if bytes < 0:
            bytes = self.length - self._buf_position
        bytes_remaining = min(bytes, self.length - self._buf_position)

        if bytes_remaining == 0:
            return ""

        if self._buf_position != self._file_position:
            buf_bytes = min(bytes_remaining, self._file_position - self._buf_position)
            old_data = self._buf.read(buf_bytes)
            bytes_remaining -= buf_bytes
        else:
            old_data = ""

        assert self._buf_position == self._file_position, (
            "Before reading buffer position (%i) didn't match file position (%i)" %
            (self._buf_position, self._file_position))
        new_data = self._file.read(bytes_remaining)
        self._buf.write(new_data)
        self._file_position += bytes_remaining
        assert self._buf_position == self._file_position, (
            "After reading buffer position (%i) didn't match file position (%i)" %
            (self._buf_position, self._file_position))

        return old_data + new_data

    def tell(self):
        return self._buf_position

    def seek(self, offset):
        if offset > self.length or offset < 0:
            raise ValueError
        if offset <= self._file_position:
            self._buf.seek(offset)
        else:
            self.read(offset - self._file_position)

    def readline(self, max_bytes=None):
        if max_bytes is None:
            max_bytes = self.length - self._buf_position

        if self._buf_position < self._file_position:
            data = self._buf.readline(max_bytes)
            if data.endswith("\n") or len(data) == max_bytes:
                return data
        else:
            data = ""

        assert self._buf_position == self._file_position

        initial_position = self._file_position
        found = False
        buf = []
        max_bytes -= len(data)
        while not found:
            readahead = self.read(min(2, max_bytes))
            max_bytes -= len(readahead)
            for i, c in enumerate(readahead):
                if c == "\n":
                    buf.append(readahead[:i+1])
                    found = True
                    break
            if not found:
                buf.append(readahead)
            if not readahead or not max_bytes:
                break
        new_data = "".join(buf)
        data += new_data
        self.seek(initial_position + len(new_data))
        return data

    def readlines(self):
        rv = []
        while True:
            data = self.readline()
            if data:
                rv.append(data)
            else:
                break
        return rv

    def next(self):
        data = self.readline()
        if data:
            return data
        else:
            raise StopIteration

    def __iter__(self):
        return self


class Request(object):
    """Object representing a HTTP request.

    .. attribute:: doc_root

    The local directory to use as a base when resolving paths

    .. attribute:: route_match

    Regexp match object from matching the request path to the route
    selected for the request.

    .. attribute:: protocol_version

    HTTP version specified in the request.

    .. attribute:: method

    HTTP method in the request.

    .. attribute:: request_path

    Request path as it appears in the HTTP request.

    .. attribute:: url_base

    The prefix part of the path; typically / unless the handler has a url_base set

    .. attribute:: url

    Absolute URL for the request.

    .. attribute:: headers

    List of request headers.

    .. attribute:: raw_input

    File-like object representing the body of the request.

    .. attribute:: url_parts

    Parts of the requested URL as obtained by urlparse.urlsplit(path)

    .. attribute:: request_line

    Raw request line

    .. attribute:: headers

    RequestHeaders object providing a dictionary-like representation of
    the request headers.

    .. attribute:: body

    Request body as a string

    .. attribute:: GET

    MultiDict representing the parameters supplied with the request.
    Note that these may be present on non-GET requests; the name is
    chosen to be familiar to users of other systems such as PHP.

    .. attribute:: POST

    MultiDict representing the request body parameters. Most parameters
    are present as string values, but file uploads have file-like
    values.

    .. attribute:: cookies

    Cookies object representing cookies sent with the request with a
    dictionary-like interface.

    .. attribute:: auth

    Object with username and password properties representing any
    credentials supplied using HTTP authentication.

    .. attribute:: server

    Server object containing information about the server environment.
    """

    def __init__(self, request_handler):
        self.doc_root = request_handler.server.router.doc_root
        self.route_match = None  # Set by the router

        self.protocol_version = request_handler.protocol_version
        self.method = request_handler.command

        scheme = request_handler.server.scheme
        host = request_handler.headers.get("Host")
        port = request_handler.server.server_address[1]

        if host is None:
            host = request_handler.server.server_address[0]
        else:
            if ":" in host:
                host, port = host.split(":", 1)

        self.request_path = request_handler.path
        self.url_base = "/"

        if self.request_path.startswith(scheme + "://"):
            self.url = request_handler.path
        else:
            self.url = "%s://%s:%s%s" % (scheme,
                                      host,
                                      port,
                                      self.request_path)
        self.url_parts = urlparse.urlsplit(self.url)

        self._raw_headers = request_handler.headers

        self.request_line = request_handler.raw_requestline

        self._headers = None

        self.raw_input = InputFile(request_handler.rfile,
                                   int(self.headers.get("Content-Length", 0)))
        self._body = None

        self._GET = None
        self._POST = None
        self._cookies = None
        self._auth = None

        self.server = Server(self)

    def __repr__(self):
        return "<Request %s %s>" % (self.method, self.url)

    @property
    def GET(self):
        if self._GET is None:
            params = urlparse.parse_qsl(self.url_parts.query, keep_blank_values=True)
            self._GET = MultiDict()
            for key, value in params:
                self._GET.add(key, value)
        return self._GET

    @property
    def POST(self):
        if self._POST is None:
            #Work out the post parameters
            pos = self.raw_input.tell()
            self.raw_input.seek(0)
            fs = cgi.FieldStorage(fp=self.raw_input,
                                  environ={"REQUEST_METHOD": self.method},
                                  headers=self.headers,
                                  keep_blank_values=True)
            self._POST = MultiDict.from_field_storage(fs)
            self.raw_input.seek(pos)
        return self._POST

    @property
    def cookies(self):
        if self._cookies is None:
            parser = Cookie.BaseCookie()
            cookie_headers = self.headers.get("cookie", "")
            parser.load(cookie_headers)
            cookies = Cookies()
            for key, value in parser.iteritems():
                cookies[key] = CookieValue(value)
            self._cookies = cookies
        return self._cookies

    @property
    def headers(self):
        if self._headers is None:
            self._headers = RequestHeaders(self._raw_headers)
        return self._headers

    @property
    def body(self):
        if self._body is None:
            pos = self.raw_input.tell()
            self.raw_input.seek(0)
            self._body = self.raw_input.read()
            self.raw_input.seek(pos)
        return self._body

    @property
    def auth(self):
        if self._auth is None:
            self._auth = Authentication(self.headers)
        return self._auth


class RequestHeaders(dict):
    """Dictionary-like API for accessing request headers."""
    def __init__(self, items):
        for key, value in zip(items.keys(), items.values()):
            key = key.lower()
            if key in self:
                self[key].append(value)
            else:
                dict.__setitem__(self, key, [value])

    def __getitem__(self, key):
        """Get all headers of a certain (case-insensitive) name. If there is
        more than one, the values are returned comma separated"""
        values = dict.__getitem__(self, key.lower())
        if len(values) == 1:
            return values[0]
        else:
            return ", ".join(values)

    def __setitem__(self, name, value):
        raise Exception

    def get(self, key, default=None):
        """Get a string representing all headers with a particular value,
        with multiple headers separated by a comma. If no header is found
        return a default value

        :param key: The header name to look up (case-insensitive)
        :param default: The value to return in the case of no match
        """
        try:
            return self[key]
        except KeyError:
            return default

    def get_list(self, key, default=missing):
        """Get all the header values for a particular field name as
        a list"""
        try:
            return dict.__getitem__(self, key.lower())
        except KeyError:
            if default is not missing:
                return default
            else:
                raise

    def __contains__(self, key):
        return dict.__contains__(self, key.lower())

    def iteritems(self):
        for item in self:
            yield item, self[item]

    def itervalues(self):
        for item in self:
            yield self[item]

class CookieValue(object):
    """Representation of cookies.

    Note that cookies are considered read-only and the string value
    of the cookie will not change if you update the field values.
    However this is not enforced.

    .. attribute:: key

    The name of the cookie.

    .. attribute:: value

    The value of the cookie

    .. attribute:: expires

    The expiry date of the cookie

    .. attribute:: path

    The path of the cookie

    .. attribute:: comment

    The comment of the cookie.

    .. attribute:: domain

    The domain with which the cookie is associated

    .. attribute:: max_age

    The max-age value of the cookie.

    .. attribute:: secure

    Whether the cookie is marked as secure

    .. attribute:: httponly

    Whether the cookie is marked as httponly

    """
    def __init__(self, morsel):
        self.key = morsel.key
        self.value = morsel.value

        for attr in ["expires", "path",
                     "comment", "domain", "max-age",
                     "secure", "version", "httponly"]:
            setattr(self, attr.replace("-", "_"), morsel[attr])

        self._str = morsel.OutputString()

    def __str__(self):
        return self._str

    def __repr__(self):
        return self._str

    def __eq__(self, other):
        """Equality comparison for cookies. Compares to other cookies
        based on value alone and on non-cookies based on the equality
        of self.value with the other object so that a cookie with value
        "ham" compares equal to the string "ham"
        """
        if hasattr(other, "value"):
            return self.value == other.value
        return self.value == other


class MultiDict(dict):
    """Dictionary type that holds multiple values for each
    key"""
    #TODO: this should perhaps also order the keys
    def __init__(self):
        pass

    def __setitem__(self, name, value):
        dict.__setitem__(self, name, [value])

    def add(self, name, value):
        if name in self:
            dict.__getitem__(self, name).append(value)
        else:
            dict.__setitem__(self, name, [value])

    def __getitem__(self, key):
        """Get the first value with a given key"""
        #TODO: should this instead be the last value?
        return self.first(key)

    def first(self, key, default=missing):
        """Get the first value with a given key

        :param key: The key to lookup
        :param default: The default to return if key is
                        not found (throws if nothing is
                        specified)
        """
        if key in self and dict.__getitem__(self, key):
            return dict.__getitem__(self, key)[0]
        elif default is not missing:
            return default
        raise KeyError

    def last(self, key, default=missing):
        """Get the last value with a given key

        :param key: The key to lookup
        :param default: The default to return if key is
                        not found (throws if nothing is
                        specified)
        """
        if key in self and dict.__getitem__(self, key):
            return dict.__getitem__(self, key)[-1]
        elif default is not missing:
            return default
        raise KeyError

    def get_list(self, key):
        """Get all values with a given key as a list

        :param key: The key to lookup
        """
        return dict.__getitem__(self, key)

    @classmethod
    def from_field_storage(cls, fs):
        self = cls()
        if fs.list is None:
            return self
        for key in fs:
            values = fs[key]
            if not isinstance(values, list):
                values = [values]

            for value in values:
                if value.filename:
                    value = value
                else:
                    value = value.value
                self.add(key, value)
        return self


class Cookies(MultiDict):
    """MultiDict specialised for Cookie values"""
    def __init__(self):
        pass

    def __getitem__(self, key):
        return self.last(key)


class Authentication(object):
    """Object for dealing with HTTP Authentication

    .. attribute:: username

    The username supplied in the HTTP Authorization
    header, or None

    .. attribute:: password

    The password supplied in the HTTP Authorization
    header, or None
    """
    def __init__(self, headers):
        self.username = None
        self.password = None

        auth_schemes = {"Basic": self.decode_basic}

        if "authorization" in headers:
            header = headers.get("authorization")
            auth_type, data = header.split(" ", 1)
            if auth_type in auth_schemes:
                self.username, self.password = auth_schemes[auth_type](data)
            else:
                raise HTTPException(400, "Unsupported authentication scheme %s" % auth_type)

    def decode_basic(self, data):
        decoded_data = base64.decodestring(data)
        return decoded_data.split(":", 1)
