import hashlib
import string
import random
import datetime

from .models import StudyToken, ParticipantToken
import logging
logger = logging.getLogger(__name__)



class StudyTokenApi(object):

    def _post(self, hash, expire_on=None):
        if not self.validate_hash(hash):
            return False
        token = StudyToken()
        if expire_on is not None:
            token.expires_on = expire_on
            logger.debug("expire_on is not None: " + str(expire_on))
        generate_token(token)
        logger.debug("generated new study token: expires_on: " + str(token.expires_on) + " token: " + str(token.token))
        return token

    def _get(self, token):
        try:
            study_token = StudyToken.objects.get(token=token)
            logger.debug("get study_token from token=%s in objects: %s", token, str(study_token))
        except:
            logger.error("no study token")
            return False

        # sloppy - why did they leave print statements?
        if study_token.expires_on is not None:
            # We are in utc time, need to make sure timezone is utc
            now_dt = datetime.datetime.utcnow()
            delta = now_dt - study_token.expires_on.replace(tzinfo=None)
            logger.debug("in study token _get study_token.expires_on:" + str(study_token.expires_on))
            if delta.days > 0:
                logger.info("token expired: " + str(delta.days) + ' days ago')
                return False
        return study_token

    def validate_hash(self, hash):
        sha256 = hashlib.sha256()
        sha256.update("{0}{1}".format("1", "abc123"))
        return sha256.hexdigest() == hash

class ParticipantTokenApi(object):

    def _post(self, participant, hash, study_token, expire_on=None):
        logger.info("ParticipantTokenApi: hash: " + str(hash) + " participant: " + str(participant))
        if not participant or participant is None:
            return False

        if not self.validate_hash(participant, hash):
            logger.error("ParticipantTokenApi: cannot validate hash:" + str(hash) + " participant: " + str(participant))
            return False

        if study_token.expires_on is not None and expire_on is not None:
            logger.debug("study_token.expires_on: " + str(study_token.expires_on))
            logger.debug("expires_on: " + str(expire_on))
            delta = expire_on - study_token.expires_on.replace(tzinfo=None)
            #if delta.days > 0:
            if delta.days > 2:
                logger.debug("delta greater than two    ")
                logger.info("token expired: " + str(delta.days) + ' days ago')
                return False

        token = ParticipantToken(
            study_token=study_token,
            participant=participant)
        if expire_on is not None:
            token.expires_on = expire_on
        generate_token(token)
        logger.debug("generated new participant token: expires_on: " + str(token.expires_on) + " token: " + str(token.token))
        return token

    def _get(self, token, study_token):
        try:
            participant_token = ParticipantToken.objects.get(token=token)
            logger.debug("get participant_token from token=%s in objects: %s", token, str(participant_token))
        except:
            logger.debug("couldn't find  participant_token from token=%s in objects: %s", token)
            return False
        if participant_token.expires_on is not None:
            # We are in utc time, need to make sure timezone is utc
            now_dt = datetime.datetime.utcnow()
            delta = now_dt - participant_token.expires_on.replace(tzinfo=None)
            if delta.days > 0:
                logger.info("token expired " + str(delta.days) + ' days ago')
                return False
        return participant_token

    def validate_hash(self, participant, hash):
        sha256 = hashlib.sha256()
        sha256.update("{0}{1}".format(participant.uuid, "abc123"))
        return sha256.hexdigest() == hash


def generate_token(token):
    hash = hashlib.sha256()
    while True:
        new_token = ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(0, 10))
        hash.update(new_token)
        try:
            token.token = hash.hexdigest()
            token.save()
            return
        except Exception as e:
            #print e
            logger.exception("cannot generate_token")
            continue
