#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# imports.
from r3sponse.v1.classes.config import *
from r3sponse.v1.classes import utils
from r3sponse.v1.classes.utils import color, symbol
from django.http import JsonResponse

# the manager class.
class R3sponse(object):
	def __init__(self):	

		# set log file.
		self.log_file = None

		# set log level.
		self.log_level = 0
		if utils.argument_present('--log-level'):
			try: self.log_level = int(utils.get_argument('--log-level'))
			except: self.log_level = 0
		#

	# response functions.
	def default_response(self):
		return ResponseObject()
	def success_response(self,
		# the message (must be param #1).
		message, 
		# additional returnable functions (must be param #2).
		variables={}, 
		# log log level of the message (int).
		log_level=None, 
		# save the error to the logs file.
		save=False,
		# return as a django JsonResponse.
		django=False,
	):
		response = self.default_response()
		response["success"] = True
		response["message"] = message
		response["error"] = None
		for key, value in variables.items():
			response[key] = value
		r3sponse.log(message=response["message"], log_level=log_level, save=save)
		if django: response = JsonResponse(response.dict(), safe=False)
		return response
	def error_response(self,
		# the error message.
		error="", 
		# log log level of the message (int).
		log_level=None, 
		# save the error to the erros file.
		save=False,
		# return as a django JsonResponse.
		django=False,
	):
		response = self.default_response()
		response["success"] = False
		response["message"] = None
		response["error"] = error
		r3sponse.log(error=response["error"], log_level=log_level, save=save)
		if django: response = JsonResponse(response.dict(), safe=False)
		return response
		#
	def success(self, response):
		if response["error"] == None:
			return True
		else: return False

	# parameter functions.
	def get_request_parameter(self, request, identifier):
		response = self.default_response()
		if request.method in ["post", "POST"]:
			variable = request.POST.get(identifier)
		else:
			variable = request.GET.get(identifier)
		if variable in ["", None]:
			return variable, self.error_response(f"Define parameter: [{identifier}].")
		return variable, self.success_response(f"Succesfully retrieved request parameter [{identifier}].")
	def get_request_parameters(self, request, identifiers=[], optional=False, empty_value=None):
		if isinstance(identifiers, str):
			return self.error_response("__get_request_params__ is used to retrieve several identifiers (array format not string).")
		params = {}
		for param in identifiers:
			param_value, response = self.get_request_parameter(request, param)
			if response["error"] != None: 
				if optional:
					params[param] = empty_value
				else:
					return params, response
			else: 
				params[param] = param_value
		if optional:
			for key in identifiers:
				try: params[key]
				except: params[key] = empty_value
		return params, self.success_response(f"Succesfully retrieved {len(params)} request parameter(s).")

	# check parameters.
	def check_parameter(self, parameter=None, name="parameter", empty_value=None):
		response = self.default_response()
		if parameter == empty_value: 
			return self.error_response(f"Define parameter [{name}].")
		else: return self.success_response(f"Succesfully checked parameter [{name}].")
	def check_parameters(self, parameters={"parameter":None}, empty_value=None):
		response = self.default_response()
		for id, value in parameters.items():
			response = self.check_parameter(value, id, empty_value=empty_value)
			if response["error"] != None: return response
		return response

	# log functions.
	def log(self, 
		# option 1:
		# the message.
		message=None,
		# option 2:
		# the error.
		error=None,
		# option 3:
		# the response dict (leave message None to use).
		response={},
		# optionals:
		# the log level for printing to console.
		log_level=0,
		# save to log file.
		save=False,
		# save errors only (for option 2 only).
		save_errors=False,
	):
		msg, _error_ = None, False
		if [message,error,response] == [None,None,{}]:
			raise ValueError("Define either parameter [message:str], [error:str] or [response:dict].")
		if response != {}:
			if response["error"] != None: 
				_error_ = True
				msg = f"Error: {response['error']}"
			else: 
				msg = response["message"]
		elif error != None: 
			msg = f"Error: {error}"
		else: 
			msg = message
		try:
			comparison = log_level != None and log_level >= self.log_level
		except TypeError as e:
			if "not supported between instances of 'dict' and 'int'" in f"{e}":
				raise TypeError(f"You most likely returned a r3sponse.error_response when you meant a r3sponse.success_response, error: {e}")
			else:
				raise TypeError(e)
		if comparison:
			print(f"{Formats.Date().seconds_timestamp} - {color.fill(msg)}")
		if save: 
			self.__log_to_file__(msg)
		elif save_errors and _error_:
			self.__log_to_file__(msg)

		#
	def load_logs(self, format="webserver", options=["webserver", "cli", "array", "string"]):
		try:
			logs = Formats.File(self.log_file, load=True, blank="").data
		except:
			return self.error_response("Failed to load the logs.")
		if format == "webserver":
			logs = logs.replace("\n", "<br>")
		elif format == "cli":
			a=1
		elif format == "array" or format == list:
			logs = logs.split("\n")
		elif format == "string" or format == str:
			logs = str(logs)
		else: 
			return self.error_response(f"Invalid format parameter [{format}], valid options: {options}.")

		return self.success_response("Succesfully loaded the logs.", {"logs":logs})
	def reset_logs(self):
		Formats.File(self.log_file).save(f"Resetted log file.\n")
		#
	
	# system functions.
	def __log_to_file__(self, message):

		# init.
		response = self.default_response()
		try:
			with open(self.log_file, "a") as file:
				file.write(f'{Formats.Date().seconds_timestamp} - {message}\n')
			response["success"] = True
			response["message"] = "Succesfully logged the message."
		except:
			response["error"] = "Failed to log the message."
			return response
		
		# check file size.
		size = Formats.FilePath(self.log_file).size(mode="mb", type="integer")
		if int(size.replace(" MB", "")) >= 100: self.reset_logs()

		# return response.
		return response

		#

# a response object.
class ResponseObject(object):
	def __init__(self):
		self.success = False
		self.message = None
		self.error = None
	# iterate over self keys & variables.
	def items(self):
		return vars(self).items()
	def keys(self):
		return list(vars(self).keys())
	def values(self):
		return list(vars(self).values())
	def dict(self):
		dictionary = {}
		for key, value in self.items():
			dictionary[key] = value
		return dictionary
	# assign self variables by dictionary.
	def assign(self, dictionary):
		if not isinstance(dictionary, dict):
			raise TypeError("You can only self assign with a dictionary as parameter.")
		for key,value in dictionary.items():
			self[key] = value
	# clean default values.
	def clean(self):
		for i in ["error", "message", "success"]:
			del self[i]
			#except: a=1
		return self
	# support item assignment.
	def __setitem__(self, key, value):
		setattr(self, key, value)
	def __getitem__(self, key):
		return getattr(self, key)
	def __delitem__(self, key):
		delattr(self, key)
	# string format.
	def __str__(self):
		return json.dumps(self.dict(), indent=4)
	def json(self,):
		return json.dumps(self, default=lambda o: o.__dict__)
	#def __dict__(self):
	#	return json.dumps(self.dict(), indent=4)

# initialized objects.
r3sponse = R3sponse()

