from functools import cached_property
from http.cookies import SimpleCookie
from http.server import BaseHTTPRequestHandler
from urllib.parse import parse_qsl, urlparse
import json

from ..oms import Oms

class WebRequestHandler(BaseHTTPRequestHandler):
	def __init__(self, request, client_address, server):
		BaseHTTPRequestHandler.__init__(self, request, client_address, server)

	@cached_property
	def url(self):
		return urlparse(self.path)

	@cached_property
	def query_data(self):
		return dict(parse_qsl(self.url.query))

	@cached_property
	def post_data(self):
		content_length = int(self.headers.get("Content-Length", 0))
		return self.rfile.read(content_length)

	@cached_property
	def form_data(self):
		return dict(parse_qsl(self.post_data.decode("utf-8")))

	@cached_property
	def cookies(self):
		return SimpleCookie(self.headers.get("Cookie"))

	def respond_with_redirect(self, url):
		self.send_response(302, "Found")
		self.send_header("Location", url)
		self.end_headers()
		self.close_connection()

	def respond_with_content(self, response_code, response_text, content_type, content):
		self.send_response(response_code, response_text)
		self.send_header("Content-Type", content_type)
		self.send_header("Content-Length", len(content))
		self.end_headers()
		self.wfile.write(content.encode("utf-8"))

	def get_oms(self) -> Oms:
		from ..oms import MySQLDatabaseOms

		if not hasattr(self, "__oms"):
			self.__oms = None

		if self.__oms is None:
			self.__oms = MySQLDatabaseOms("localhost", 13306, "mocha_user", "9Q5eLsKfL5AciM4U", "mocha_test")

		return self.__oms

	def do_GET(self):
		oms = self.get_oms()

		default_tenant_name = "super"

		path = self.url.path.split('/')
		path = path[1:]
		
		if (len(path) == 1 and path[0] == ""):
			self.respond_with_redirect("/" + default_tenant_name)
			return

		if (len(path) > 0):
		
			tenant_name = path[0]

			if len(path) == 1:
				self.respond_with_redirect("/madi/authgwy/" + tenant_name + "/login.htmld")
				return

			if len(path) > 1:
				if tenant_name == "madi":
					authgwy = path[1]
					if authgwy == "authgwy":
						if len(path) == 4:
							tenant_name = path[2]
							file_name = path[3]

							tenant = oms.get_tenant_by_name(tenant_name)
							if tenant is None:
								pass
							else:
								print(tenant.get_name())

							if file_name == "login.htmld":
								from .pages import LoginWebPage
								page = LoginWebPage()
								self.respond_with_content(200, "OK", "application/xhtml+xml", page.render_html())
								return
							elif file_name == "tenant-config.xml":
								content = self.get_tenant_config_xml(tenant_name)
								self.respond_with_content(200, "OK", "application/xml", content)
								return

							elif file_name == "images":
								if len(path) >= 5:
									if path[4] == "signon.xml":
										return self.respond_with_header_image(tenant_name)
				else:
					if len(path) > 1:
						if path[1] == "d":
							if len(path) > 2:
								if path[2] == "home.htmld":
									from .pages import HomeWebPage
									page = HomeWebPage()
									self.respond_with_content(200, "OK", "application/xhtml+xml", page.render_html())

				jj = self.get_json_response()
				if jj["result"] == "failure" and jj["remedy"] == "login":
					self.respond_with_login_page(tenant_name)
					return

		self.send_response(200)
		self.send_header("Content-Type", "application/json")
		self.end_headers()
		self.wfile.write(self.get_response().encode("utf-8"))

	def do_POST(self):
		self.do_GET()

	def respond_with_header_image(self, tenant_name):
		return None

	def respond_with_login_page(self, tenant_name):

		self.send_response(200)
		self.send_header("Content-Type", "application/json")
		self.end_headers()
		self.wfile.write(self.get_response().encode("utf-8"))
		

	def get_response(self):
		jj = self.get_json_response()
		if jj["result"] == "failure" and jj["remedy"] == "login":
			self.respond_with_login_page()

		return json.dumps(jj)

	def get_singleline_xml(self, tag_name, content_dict):
		sz = """<?xml version="1.0" encoding="UTF-8" standalone="yes"?>"""
		sz += "<" + tag_name + " "
		for key in content_dict:
			val = content_dict[key]
			sz += key + "=\"" + val + "\" "
		sz += "/>"
		return sz


	def get_tenant_config_xml(self, tenant_name : str):
		oms = self.get_oms()
		tenant = oms.get_tenant_by_name(tenant_name)

		return self.get_singleline_xml("mcu:Tenant_Config", {
			"xmlns:mcu": "urn:net.alcetech.schemas.Mocha.UserInterface",

			"Allow_Attachments_And_Documents_To_Be_Shared_With_Other_Mobile_Apps": "0",
			"Apns_Allowed": "0",
			"Canvas_Is_Enabled": "1",
			"Canvas_Hex_Code": "#005cb9,#0875e1",
			"Clear_Mobile_SSO_Webview_Cookies_on_Login": "0",
			"Deter_Screenshots": "0",
			"Disable_Add_To_Contact": "0",
			"Disable_Importing_Attachments_From_Third-Party_Cloud_Services": "0",
			"Disable_Location_Service": "0",
			"Disable_Mail_To": "0",
			"Disable_Voice_in_Assistant_on_Mobile": "1",
			"Enable_Blue_Primary_Buttons": "0",
			"Enable_Certificate_Based_SSO": "0",
			"Enable_DOM_Storage": "0",
			"Enable_Email_Annotations": "1",
			"Enable_export_to_Worksheets": "1",
			"Enable_Fingerprint_Authentication": "1",
			"Enable_Geospace_Visualization": "0",
			"Enable_Mobile_Browser_SSO_for_Native_Apps": "0",
			"Enable_New_Profile": "0",
			"Error_Message_for_Browser": "This Browser is not supported by Workday. Please contact your IT department.",
			"Is_FedRAMP_Tenant": "0",
			"Google_Cloud_Messaging_Project_Number": "739632724832",
			"Hide_Links_to_Web_from_Deep_Linking_and_Inbox": "0",
			"Login_URL": "https://wd5.myworkday.com/cityoforlando/login-saml2.flex",
			"Logout_URL": "https://cityoforlando.okta.com",
			"OMS_Note": "PROD - Powered by Workday",
			"Pin_Auth_Enabled": "0",
			"Pin_Max_Attempts": "0",
			"Pin_Max_Length": "0",
			"Pin_Min_Length": "0",
			"Reset_Password_Online": "0",
			"Show_Change_Password_Link": "1",
			"Show_Forgotten_Password_Link": "0",
			"SignOn_Custom_Message": "&lt;p&gt;City of Orlando - Production&lt;/p&gt;",
			"SignOn_Message_Locale": "en_US",
			"SignOn_Note": "&lt;p&gt;City of Orlando - Production&lt;/p&gt;",
			"SignOn_Tenant_Logo_Url": "/cityoforlando/images/signon.xml",
			"System_Confidence_Level": "PROD",
			"System_Note": oms.get_attribute_value(tenant.get_instance(), oms.get_instance_by_global_identifier('')), # "Your system will be unavailable for a maximum of 3 hours during the next Weekly Service Update; starting on Friday, October 27, 2023 at 11:00 PM PDT (GMT-7) until Saturday, October 28, 2023 at 2:00 AM PDT (GMT-7).",
			"Use_One_Time_Use_Link": "0"
		})

	def get_json_response(self):
		path = self.url.path.split('/')
		path = path[1:]

		tenantName = path[0]
		if tenantName == "madi":
			authgwy = path[1]
			if authgwy == "authgwy":
				if len(path) == 4:
					tenantName = path[2]
					loginPage = path[3]
				else:
					# error out
					return
			else:
				# error out
				return
		
		from ..core import InstanceKey
		from ..oms import MySQLDatabaseOms

		oms = MySQLDatabaseOms("localhost", 13306, "mocha_user", "9Q5eLsKfL5AciM4U", "mocha_test")

		if len(path) > 3:
			if path[1] == "api":
					
				if path[2] == "instances":

					ik = InstanceKey.parse(path[3])
					inst = oms.get_instance_by_key(ik)
					if inst is None:
						jj = {
							"result": "error",
							"message": "invalid inst " + str(ik)
						}
						return jj

					jj = {
						"result": "success",
						"iid": str(inst.get_instance_key()),
						"gid": inst.get_global_identifier()
					}
					return jj
				
			else:

				jj = {
					"result": "error",
					"message": "invalid request"
				}
				return jj

		else:
			jj = {
				"result": "error",
				"message": "invalid request"
			}

		return jj
