import datetime, json, logging, uuid
from . import LANGUAGES, RE_CHALLENGE_ID, RE_USER_ID
from .StorageHelper import StorageKeys, get_redis, wait_for_redis

# -------------------------------------------------------------------

@wait_for_redis
def CreateSubmission(lang, user_id, challenge_id, code, simulation=None):
	# Language
	lang = lang.strip()
	if not lang in LANGUAGES:
		logging.error('Language is invalid')
		return None

	# User
	user_id = user_id.strip()
	if not RE_USER_ID.match(user_id):
		logging.error('User is invalid')
		return None
	user = get_redis().hget(StorageKeys.Users, user_id)
	if not user:
		logging.error('User is Unknown')
		return None

	# Challenge
	challenge_id = challenge_id.strip()
	if not RE_CHALLENGE_ID.match(challenge_id):
		logging.error('Challenge is invalid')
		return None
	from .ChallengeHelper import LoadChallenge
	if not LoadChallenge(challenge_id):
		logging.error('Challenge is unknown')
		return None

	# Code
	code = code.replace('\r', '')
	if not code:
		logging.error('Code is invalid')
		return None

	# Execute
	submission_id = str(uuid.uuid4())
	submission = {
		'challenge_id': challenge_id,
		'code': code,
		'id': submission_id,
		'lang': lang,
		'stamp': datetime.datetime.utcnow().timestamp(),
		'user_id': user_id
	}
	if simulation != None:
		if not isinstance(simulation, int):
			logging.error('Simulation is invalid: %s', simulation)
			return None
		submission['simulation'] = simulation

	pipe = get_redis().pipeline()
	pipe.hset(StorageKeys.Submissions, submission_id, json.dumps(submission))
	pipe.lpush(StorageKeys.SubmissionsQueue, submission_id)
	pipe.execute()

	return submission

# -------------------------------------------------------------------

@wait_for_redis
def LoadSubmissions():
	return [ json.loads(submission) for submission_id, submission in get_redis().hgetall(StorageKeys.Submissions).items() ]

# -------------------------------------------------------------------

@wait_for_redis
def LoadSubmission(submission_id):
	submission = get_redis().hget(StorageKeys.Submissions, submission_id)
	return json.loads(submission) if submission else None

# -------------------------------------------------------------------

@wait_for_redis
def WaitSubmission():
	logging.info('Wait submission')
	submission_id = get_redis().brpoplpush(StorageKeys.SubmissionsQueue, StorageKeys.SubmissionsQueueWIP, 0)
	logging.info('Load submission %s', submission_id)
	return json.loads(get_redis().hget(StorageKeys.Submissions, submission_id))

# -------------------------------------------------------------------
