package gov.va.vinci.dart.biz;

import gov.va.vinci.dart.common.exception.ObjectNotFoundException;
import gov.va.vinci.dart.service.DartObjectFactory;

import java.util.List;
import java.util.Set;

import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinTable;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;

@Entity
@Table(name="`group`",schema="hib")
public class Group extends ReferenceObject {
	
	private static final int GROUP_ID_NDS = 1;
	private static final int GROUP_ID_PRIVACY = 3;
	private static final int GROUP_ID_SECURITY = 5;
	private static final int GROUP_ID_ORD = 7;
	private static final int GROUP_ID_OEFOIF = 9;
	private static final int GROUP_ID_SQDUG = 11;
	private static final int GROUP_ID_CAPRI = 13;
	private static final int GROUP_ID_VISTAWEB = 14;
	private static final int GROUP_ID_DART_ADMIN = 15;
	private static final int GROUP_ID_HOMELESS_REGISTRY = 16;
	
	public static Group NDS;
	public static Group PRIVACY;
	public static Group SECURITY;
	public static Group ORD;
	public static Group OEFOIF;
	public static Group SQDUG;
	public static Group CAPRI;
	public static Group VISTAWEB;
	public static Group DART_ADMIN;
	public static Group HOMELESS_REGISTRY;
	
	private static boolean initialized = false;
	
	public static void initialize() {
		if (initialized == true) {
			return;
		}
		
		try {
			NDS = Group.findById(GROUP_ID_NDS);
			PRIVACY = Group.findById(GROUP_ID_PRIVACY);
			SECURITY = Group.findById(GROUP_ID_SECURITY);
			ORD = Group.findById(GROUP_ID_ORD);
			OEFOIF = Group.findById(GROUP_ID_OEFOIF);
			SQDUG = Group.findById(GROUP_ID_SQDUG);
			CAPRI = Group.findById(GROUP_ID_CAPRI);
			VISTAWEB = Group.findById(GROUP_ID_VISTAWEB);
			DART_ADMIN = Group.findById(GROUP_ID_DART_ADMIN);
			HOMELESS_REGISTRY = Group.findById(GROUP_ID_HOMELESS_REGISTRY);
			
			initialized = true;	//initialized all of the groups
		}
		catch (ObjectNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	@ManyToMany(fetch=FetchType.LAZY)
	@JoinTable(
		      name="persongroup", schema="hib",
		      joinColumns={@JoinColumn(name="groupid", referencedColumnName="ID")},
		      inverseJoinColumns={@JoinColumn(name="personid", referencedColumnName="ID")})
	Set<Person> members;

	@ManyToMany
	@JoinTable(
		      name="grouprole", schema="hib",
		      joinColumns={@JoinColumn(name="groupid", referencedColumnName="ID")},
		      inverseJoinColumns={@JoinColumn(name="roleid", referencedColumnName="ID")})
	Set<Role> supportedRoles;
	
	@ManyToMany(fetch=FetchType.LAZY)
	@JoinTable(
		      name="documenttemplatereviewgroup", schema="hib",
		      joinColumns={@JoinColumn(name="groupid", referencedColumnName="ID")},
		      inverseJoinColumns={@JoinColumn(name="documenttemplateid", referencedColumnName="ID")})
	Set<DocumentTemplate> documentTemplatesToHide;

	@OneToOne(fetch=FetchType.LAZY,mappedBy="group")
	GroupMailbox groupMailbox;


	public static Group findById(final int groupId) throws ObjectNotFoundException {
		return DartObjectFactory.getInstance().getGroupDAO().findById(groupId);
	}
	
	public static Group findByName(final String name) throws ObjectNotFoundException {
		if (name == null || name.length() < 0 || name.length() > 64) {
			throw new ObjectNotFoundException();
		}
		
		return DartObjectFactory.getInstance().getGroupDAO().findByName(name);
	}

	public Set<Person> getMembers() {
		return members;
	}
	
	public void setMembers(final Set<Person> members) {
		this.members = members;
	}
	
	public static List<Group> listAll() { 
		return DartObjectFactory.getInstance().getGroupDAO().listAll();
	}

	public boolean supportsRole(final Role role) {
		if (role == null) {
			return false;
		}
		
		return supportedRoles.contains(role);
	}
	
	public Set<Role> getSupportedRoles() {
		return supportedRoles;
	}

	public void setSupportedRoles(Set<Role> supportedRoles) {
		this.supportedRoles = supportedRoles;
	}
	
	public Set<DocumentTemplate> getDocumentTemplatesToHide() {
		return documentTemplatesToHide;
	}
	
	public GroupMailbox getGroupMailbox() {
		return groupMailbox;
	}

	public void setGroupMailbox(GroupMailbox groupMailbox) {
		this.groupMailbox = groupMailbox;
	}


	/**
	 * Returns the "short name", used in the UI and in event/email creation
	 * @return
	 */
	public String getShortName() {
		String name = getName();

		switch( id ) {

			case GROUP_ID_NDS:
				return "NDS";
			
			case GROUP_ID_PRIVACY:
				return "Privacy";
			
			case GROUP_ID_SECURITY:
				return "Security";
			
			case GROUP_ID_ORD:
				return "ORD";
			
			case GROUP_ID_OEFOIF:
				return "OEF-OIF";
			
			case GROUP_ID_SQDUG:
				return "SQDUG";
				
			case GROUP_ID_CAPRI:
				return "CAPRI";
				
			case GROUP_ID_VISTAWEB:
				return "VistAWeb";		
				
			case GROUP_ID_DART_ADMIN:
				return "DART ADMIN";
				
			case GROUP_ID_HOMELESS_REGISTRY:
				return "Homeless Registry";
		}
		
		return name;
	}
	

	/**
	 * Returns the workflow status display name, used in the UI
	 * @return
	 */
	public String getStatusDisplayName() {
		String name = getName();

		switch( id ) {

			case GROUP_ID_NDS:
				return "NDS";

			case GROUP_ID_OEFOIF:
				return "OEF";
			
			case GROUP_ID_SQDUG:
				return "SQDUG";

		}
		
		return name;
	}
	

	/**
	 * Returns the workflow status display name, used in the UI
	 * @return
	 */
	public static String getStatusDisplayName( final int groupId ) {

		switch( groupId ) {

			case GROUP_ID_NDS:
				return "NDS";
			
			case GROUP_ID_OEFOIF:
				return "OEF";
			
			case GROUP_ID_SQDUG:
				return "SQDUG";
		}
		
		return "";
	}



	@Override
	public int hashCode() {
		return id;
	}
	
	// necessary to use (Set<Group>).contains()
	@Override
	public boolean equals(Object obj) {
		if (obj == null) {
			return false;
		}
		
//		if( Group.class.isAssignableFrom(obj.getClass()) == false && 
//			obj.getClass().isAssignableFrom(Group.class) == false ) {
		if ((obj instanceof Group) == false) {
			return false;
		}
		
		Group rs2 = (Group)obj;
		return rs2.getId() == this.getId();
	}
}
