from os.path import splitext

import requests
import os

from shutil import copy2, Error, copystat
import json


class TokenAuth(requests.auth.AuthBase):
    def __init__(self, token):
        self.token = token

    def __call__(self, r):
        r.headers['Authorization'] = 'Token ' + self.token
        return r


def copytree(src, dst, symlinks=False, allowed_extension = None):
    names = os.listdir(src)
    if allowed_extension is None:
        allowed_extension = []
    os.makedirs(dst)
    errors = []
    for name in names:
        _, file_extension = splitext(name)
        if file_extension not in allowed_extension:
            continue
        srcname = os.path.join(src, name)
        dstname = os.path.join(dst, name)
        try:
            if symlinks and os.path.islink(srcname):
                linkto = os.readlink(srcname)
                os.symlink(linkto, dstname)
            elif os.path.isdir(srcname):
                copytree(srcname, dstname, symlinks, allowed_extension)
            else:
                copy2(srcname, dstname)
            # XXX What about devices, sockets etc.?
        except (IOError, os.error) as why:
            errors.append((srcname, dstname, str(why)))
        # catch the Error from the recursive copytree so that we can
        # continue with other files
        except Error as err:
            errors.extend(err.args[0])
    try:
        copystat(src, dst)
    except WindowsError:
        # can't copy file access times on Windows
        pass
    except OSError as why:
        errors.extend((src, dst, str(why)))
    if errors:
        raise Error(errors)

def request_server_post(url, **kwargs):
    try:
        # Allow a 30s timeout for the request.
        response = requests.post(url, timeout=30, **kwargs)
    except requests.Timeout:
        return False, None, None, "server side timeout"
    except:
        return False, None, None, "server side unknown error"

    if not response:
        return False, None, None, "server side empty response"

    status_code = response.status_code
    try:
        response_body = json.loads(response.text)
    except:
        response_body = {}

    return True, status_code, response_body, None