from django.template.defaultfilters import slugify
import random
import string

# pdf tools
import os
from django.conf import settings

# from xhtml2pdf import pisa

from django.db.models import AutoField

from math import sin, cos, radians, acos
EARTH_RADIUS_IN_MILES = 3958.761


def to_datetime(datestring):
    from datetime import datetime, timedelta
    from email.utils import parsedate_tz

    # if datestring:
    time_tuple = parsedate_tz(datestring.strip())
    raise Exception(datestring)
    if time_tuple:
        dt = datetime(*time_tuple[:6])
        return dt - timedelta(seconds=time_tuple[-1])
    else:
        return False


def is_valid_email(email):
    from django.core.validators import validate_email
    from django.core.exceptions import ValidationError
    try:
        validate_email(email)
        return True
    except ValidationError:
        return False


def handle_uploaded_file(f, filename, private=False):
    if private:
        destination = open("%s/exam_applications/%s" % (settings.PRIVATE_FILES, filename), 'wb+')
    else:
        destination = open("%s/%s" % (settings.MEDIA_ROOT, filename), 'wb+')

    for chunk in f.chunks():
        destination.write(chunk)
    destination.close()

    return filename


def slugify_unique(value, model, slugfield="slug"):
    suffix = 0
    potential = base = slugify(value)
    while True:
        if suffix:
            potential = "-".join([base, str(suffix)])
        if not model.objects.filter(**{slugfield: potential}).count():
            return potential
        suffix += 1


def random_string_unique(number, model, field):

    while True:
        random_str = ''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(number))

        if not model.objects.filter(**{field: random_str}).count():
            return random_str


def generate_random_password(number):

    random_str = ''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(number))

    return random_str


def copy_model_instance(obj):
    initial = dict([(f.name, getattr(obj, f.name))
                    for f in obj._meta.fields
                    if not isinstance(f, AutoField) and f not in obj._meta.parents.values()])
    return obj.__class__(**initial)


def calc_dist_fixed(lat_a, long_a, lat_b, long_b):
    """all angles in degrees, result in miles"""
    lat_a = radians(lat_a)
    lat_b = radians(lat_b)
    delta_long = radians(long_a - long_b)
    cos_x = (
        sin(lat_a) * sin(lat_b) +
        cos(lat_a) * cos(lat_b) * cos(delta_long)
        )
    return acos(cos_x) * EARTH_RADIUS_IN_MILES


# Convert HTML URIs to absolute system paths so xhtml2pdf can access those resources
def link_callback(uri, rel):
    # use short variable names
    sUrl = settings.STATIC_URL      # Typically /static/
    sRoot = settings.STATIC_ROOT    # Typically /home/userX/project_static/
    mUrl = settings.MEDIA_URL       # Typically /static/media/
    mRoot = settings.MEDIA_ROOT     # Typically /home/userX/project_static/media/

    # convert URIs to absolute system paths
    if uri.startswith(mUrl):
        path = os.path.join(mRoot, uri.replace(mUrl, ""))
    elif uri.startswith(sUrl):
        path = os.path.join(sRoot, uri.replace(sUrl, ""))

    # make sure that file exists
    if not os.path.isfile(path):
        raise Exception('media URI must start with %s or %s' % (sUrl, mUrl))
    return path


def split(arr, size):
    arrs = []
    while len(arr) > size:
        pice = arr[:size]
        arrs.append(pice)
        arr = arr[size:]
    arrs.append(arr)
    return arrs


def suffix(d):
    return 'th' if 11 <= d <= 13 else {1: 'st', 2: 'nd', 3: 'rd'}.get(d % 10, 'th')


def custom_strftime(format, t):
    return t.strftime(format).replace('{S}', str(t.day) + suffix(t.day))
