from ..core import InstanceKey, InstanceReference, TenantReference
from ..definitions import KnownClassGuids, KnownInstanceGuids, KnownAttributeGuids, KnownRelationshipGuids

from framework import Guid

class Oms:
	def __init__(self):
		pass

	def get_user_by_username(self, username : str):
		ik_User = self.get_instance_by_global_identifier(KnownClassGuids.User)
		if ik_User is None:
			print ("error: class `User` is not defined")
			return None
		
		users = self.get_instances(ik_User)
		for user in users:
			un = self.get_attribute_value(user, self.get_instance_by_global_identifier(KnownAttributeGuids.UserName))
			if un == username:
				return user
			
		return None

	def create_class(self, class_id : int, inst_id : int, name : str, global_identifier : Guid):
		pass

	def create_relationship(self, src_class : InstanceReference, type : str, dst_class : InstanceReference, singular : bool = False, sibling_relationship : InstanceReference = None, global_identifier : Guid = None):
		
		ik_current = self.create_instance_of(self.get_instance_by_global_identifier(KnownClassGuids.Relationship), global_identifier)
		
		self.assign_relationship(ik_current, self.get_instance_by_global_identifier(KnownRelationshipGuids.Relationship__has_source__Class), src_class)
		self.assign_attribute(ik_current, self.get_instance_by_global_identifier(KnownAttributeGuids.RelationshipType), type)
		self.assign_relationship(ik_current, self.get_instance_by_global_identifier(KnownRelationshipGuids.Relationship__has_destination__Class), dst_class)
		self.assign_attribute(ik_current, self.get_instance_by_global_identifier(KnownAttributeGuids.Singular), singular)
		
		if sibling_relationship is not None:
			self.assign_relationship(ik_current, self.get_instance_by_global_identifier(KnownRelationshipGuids.Relationship__has_sibling__Relationship), sibling_relationship)
		
		return ik_current
	
	def assign_attribute(self, instance : InstanceReference, attribute : InstanceReference, value : str):
		pass

	def assign_relationship(self, instance : InstanceReference, relationship : InstanceReference, related_instances : InstanceReference|list):
		pass
	
	def get_attribute_value(self, inst : InstanceReference, att : InstanceReference, default_value = None):
		pass

	def set_attribute_value(self, inst : InstanceReference, att : InstanceReference, value):
		pass

	def get_instance_by_key(self, key : InstanceKey):
		pass

	def get_instance_by_global_identifier(self, global_identifier : Guid):
		pass

	def get_instances(self, of_class : InstanceReference = None):
		pass

	def get_tenant_by_name(self, tenant_name : str) -> TenantReference:
		pass

	def create_instance_of(self, class_inst : InstanceReference, global_identifier : Guid = None):
		pass

	def before_init(self):
		pass

	def _init(self):
		ik_Class = self.create_class(1, 1, 'Class', KnownClassGuids.Class)
		self.create_class(1, 2, 'Attribute', KnownClassGuids.Attribute)
		ik_Relationship = self.create_class(1, 3, 'Relationship', KnownClassGuids.Relationship)

		self.create_class(1, 4, 'Text Attribute', KnownClassGuids.TextAttribute)
		self.create_class(1, 5, 'Boolean Attribute', KnownClassGuids.BooleanAttribute)
		self.create_class(1, 6, 'Element', KnownClassGuids.Element)
		self.create_class(1, 20, 'Numeric Attribute', KnownClassGuids.NumericAttribute)
		
		self.create_instance_of(self.get_instance_by_global_identifier(KnownClassGuids.TextAttribute), KnownAttributeGuids.Name)
		self.create_instance_of(self.get_instance_by_global_identifier(KnownClassGuids.TextAttribute), KnownAttributeGuids.Value)
		self.create_instance_of(self.get_instance_by_global_identifier(KnownClassGuids.TextAttribute), KnownAttributeGuids.Token)
		
		rel_Relationship__has_source__Class = self.create_instance_of(self.get_instance_by_global_identifier(KnownClassGuids.Relationship), KnownRelationshipGuids.Relationship__has_source__Class)
		rel_Relationship__has_destination__Class = self.create_instance_of(self.get_instance_by_global_identifier(KnownClassGuids.Relationship), KnownRelationshipGuids.Relationship__has_destination__Class)
		rel_Relationship__has_sibling__Relationship = self.create_instance_of(self.get_instance_by_global_identifier(KnownClassGuids.Relationship), KnownRelationshipGuids.Relationship__has_sibling__Relationship)
		
		ik_Singular = self.create_instance_of(self.get_instance_by_global_identifier(KnownClassGuids.BooleanAttribute), KnownAttributeGuids.Singular)
		ik_RelationshipType = self.create_instance_of(self.get_instance_by_global_identifier(KnownClassGuids.TextAttribute), KnownAttributeGuids.RelationshipType)
		
		ik_User = self.create_class(1, 39, 'System User', KnownClassGuids.User)
		ik_UserLogin = self.create_class(1, 4328, 'System Account Signon', KnownClassGuids.UserLogin)

		ik_UserName = self.create_instance_of(self.get_instance_by_global_identifier(KnownClassGuids.TextAttribute), KnownAttributeGuids.UserName)
		self.assign_attribute(ik_UserName, self.get_instance_by_global_identifier(KnownAttributeGuids.Name), "User Name")

		ik_PasswordHash = self.create_instance_of(self.get_instance_by_global_identifier(KnownClassGuids.TextAttribute), KnownAttributeGuids.PasswordHash)
		self.assign_attribute(ik_PasswordHash, self.get_instance_by_global_identifier(KnownAttributeGuids.Name), "Password Hash")

		ik_PasswordSalt = self.create_instance_of(self.get_instance_by_global_identifier(KnownClassGuids.TextAttribute), KnownAttributeGuids.PasswordSalt)
		self.assign_attribute(ik_PasswordSalt, self.get_instance_by_global_identifier(KnownAttributeGuids.Name), "Password Salt")

		superuser = self.create_instance_of(self.get_instance_by_global_identifier(KnownClassGuids.User), KnownInstanceGuids.User.superuser)
		self.assign_attribute(superuser, ik_UserName, "superuser")
		self.assign_attribute(superuser, ik_PasswordHash, "0bdbeeecd24e93a0d84ff2946c519761d4db2c52d9449d2de5bf3b74a8bcdfbee9d72bb88121a63700d09554983e7f881021ecf493f83dec19e8f7e465529c34")
		self.assign_attribute(superuser, ik_PasswordSalt, "5e28b86839ed4ca9838c112723aeaa27")

		self.assign_attribute(self.get_instance_by_key(InstanceKey(1, 2)), self.get_instance_by_key(InstanceKey(4, 1)), 'Attribute')
		self.assign_attribute(self.get_instance_by_key(InstanceKey(1, 3)), self.get_instance_by_key(InstanceKey(4, 1)), 'Relationship')
		self.assign_attribute(self.get_instance_by_key(InstanceKey(1, 4)), self.get_instance_by_key(InstanceKey(4, 1)), 'Text Attribute')
		self.assign_attribute(self.get_instance_by_key(InstanceKey(4, 1)), self.get_instance_by_key(InstanceKey(4, 1)), 'Name')
		self.assign_attribute(self.get_instance_by_key(InstanceKey(4, 2)), self.get_instance_by_key(InstanceKey(4, 1)), 'Value')
		self.assign_attribute(self.get_instance_by_key(InstanceKey(4, 3)), self.get_instance_by_key(InstanceKey(4, 1)), 'Token')

		ik_User_Login__for__User = self.create_relationship(ik_UserLogin, "for", ik_User, False, None, KnownRelationshipGuids.User_Login__has__User)
		# self.create_relationship(ik_User, "has", ik_UserLogin, False, ik_User_Login__for__User, KnownRelationshipGuids.User__has__User_Login)

		self.update_relationship(rel_Relationship__has_source__Class, ik_Relationship, "has source", ik_Class, True, None)
		self.update_relationship(rel_Relationship__has_destination__Class, ik_Relationship, "has destination", ik_Class, True, None)
		self.update_relationship(rel_Relationship__has_sibling__Relationship, ik_Relationship, "has sibling", ik_Relationship, True, None)
		
	def update_relationship(self, relationship : InstanceReference, src_class : InstanceReference, type : str, dst_class : InstanceReference, singular: bool, sibling_relationship : InstanceReference):
		self.assign_relationship(relationship, self.get_instance_by_global_identifier(KnownRelationshipGuids.Relationship__has_source__Class), src_class)
		self.assign_attribute(relationship, self.get_instance_by_global_identifier(KnownAttributeGuids.RelationshipType), type)
		self.assign_relationship(relationship, self.get_instance_by_global_identifier(KnownRelationshipGuids.Relationship__has_destination__Class), dst_class)
		self.assign_attribute(relationship, self.get_instance_by_global_identifier(KnownAttributeGuids.Singular), singular)
		
		if sibling_relationship is not None:
			self.assign_relationship(relationship, self.get_instance_by_global_identifier(KnownRelationshipGuids.Relationship__has_sibling__Relationship), sibling_relationship)
	
	def after_init(self):
		pass

	def init(self):
		self.before_init()
		self._init()
		self.after_init()