import urlparse
import socket

from django.core.validators import URLValidator, EmailValidator
from django.core.exceptions import ValidationError


class NetworkHelper(object):
    """
    Helper functions for parsing URLs and validating emails and URLs
    """

    @staticmethod
    def get_hostname_from_url(url):
        """
        Extracts hostname from an URL in the format
         <scheme>://<username>:<password>@<hostname>:<port>/<path>;<params>?<query>#<fragment>
        @param url: URL to process
        @type url: str
        """
        p = urlparse.urlparse(url)
        return p.hostname

    @staticmethod
    def get_scheme_from_url(url):
        """
        Extracts scheme from an URL in the format
         <scheme>://<username>:<password>@<hostname>:<port>/<path>;<params>?<query>#<fragment>
        @param url: URL to process
        @type url: str
        """
        p = urlparse.urlparse(url)
        return p.scheme

    @staticmethod
    def get_path_from_url(url):
        """
        Extracts path from an URL in the format
         <scheme>://<username>:<password>@<hostname>:<port>/<path>;<params>?<query>#<fragment>
        @param url: URL to process
        @type url: str
        """
        p = urlparse.urlparse(url)
        return p.path

    @staticmethod
    def get_port_from_url(url):
        """
        Extracts port from an URL in the format
         <scheme>://<username>:<password>@<hostname>:<port>/<path>;<params>?<query>#<fragment>
        @param url: URL to process
        @type url: str
        """
        p = urlparse.urlparse(url)
        return p.port

    @staticmethod
    def get_username_from_url(url):
        """
        Extracts username from an URL in the format
         <scheme>://<username>:<password>@<hostname>:<port>/<path>;<params>?<query>#<fragment>
        @param url: URL to process
        @type url: str
        """
        p = urlparse.urlparse(url)
        return p.username

    @staticmethod
    def get_password_from_url(url):
        """
        Extracts password from an URL in the format
         <scheme>://<username>:<password>@<hostname>:<port>/<path>;<params>?<query>#<fragment>
        @param url: URL to process
        @type url: str
        """
        p = urlparse.urlparse(url)
        return p.password

    @staticmethod
    def get_params_from_url(url):
        """
        Extracts params from an URL in the format
         <scheme>://<username>:<password>@<hostname>:<port>/<path>;<params>?<query>#<fragment>
        @param url: URL to process
        @type url: str
        """
        p = urlparse.urlparse(url)
        return p.params

    @staticmethod
    def get_query_string_from_url(url):
        """
        Extracts query from an URL in the format
         <scheme>://<username>:<password>@<hostname>:<port>/<path>;<params>?<query>#<fragment>
        @param url: URL to process
        @type url: str
        """
        p = urlparse.urlparse(url)
        return urlparse.parse_qs(p.query, keep_blank_values=True, strict_parsing=True)

    @staticmethod
    def get_ip_from_hostname(hostname):
        """
        Resolves a hostname and returns the corresponding IP address
        @param hostname: Hostname to resolve
        @type hostname: str
        """
        return socket.gethostbyname(hostname)

    @staticmethod
    def is_valid_url(url):
        """
        Validates a URL

        @param url: URL to validate
        @type url: str
        @rtype: bool
        """
        #Get a validator instance
        validator = URLValidator()
        try:
            #Validate URL
            validator(url)
            return True
        except ValidationError:
            return False

    @staticmethod
    def is_valid_email(email):
        """
        Validates an email

        @param email: eMail to validate
        @type email: str
        @rtype: bool
        """
        #Get a validator instance
        validator = EmailValidator()
        try:
            #Validate email
            validator(email)
            return True
        except ValidationError:
            return False

    @staticmethod
    def is_absolute_url(url):
        """
        Validates if a URL is relative or absolute

        @param url: URL to validate
        @type url: str
        @rtype: bool
        """
        return bool(urlparse.urlparse(url).netloc)

