<commit_before>/**
 *    Copyright 2013 <NAME> (github.com/thnaeff)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 */
package ch.thn.gedcom.creator;


import java.util.ArrayList;
import java.util.Arrays;

import ch.thn.gedcom.GedcomFormatter;
import ch.thn.gedcom.creator.GedcomCreatorEnums.NameType;
import ch.thn.gedcom.creator.GedcomCreatorEnums.Sex;
import ch.thn.gedcom.creator.GedcomCreatorEnums.YesNo;
import ch.thn.gedcom.data.GedcomNode;
import ch.thn.gedcom.store.GedcomStore;

/**
 * @author <NAME> (github.com/thnaeff)
 *
 */
public class GedcomCreatorIndividual extends GedcomCreatorStructure {
		
	
	/**
	 * An INDIVIDUAL_RECORD
	 * 
	 * @param store
	 * @param id
	 */
	public GedcomCreatorIndividual(GedcomStore store, String id) {
		super(store, "INDIVIDUAL_RECORD", "INDI");
		
		if (!setId(id)) {
			throw new GedcomCreatorError("Failed to create individual with ID " + 
					id + ". Id could not be set.");
		}
	}
	
	/**
	 * 
	 * 
	 * @param store
	 * @param node
	 */
	public GedcomCreatorIndividual(GedcomStore store, GedcomNode node) {
		super(store, "INDIVIDUAL_RECORD", node, "INDI");
	}
	
	/**
	 * 
	 * 
	 * @param id
	 * @return
	 * @throws GedcomCreatorError
	 */
	public boolean setId(String id) {
		if (id == null || id.length() == 0) {
			throw new GedcomCreatorError("Setting an empty ID is not allowed");
		}
		
		return apply(new GedcomXRef(false, id));
	}
	
	/**
	 * 
	 * 
	 * @return
	 */
	public String getId() {
		return getXRef();
	}
	
	/**
	 * 
	 * 
	 * @param sex
	 * @return
	 */
	public boolean setSex(Sex sex) {
		return apply(new GedcomValue(false, sex.value, 
				"SEX"));
	}
	
	/**
	 * 
	 * 
	 * @return
	 */
	public Sex getSex() {
		String sex = getValue("SEX");
		
		if (Sex.MALE.value.equals(sex)) {
			return Sex.MALE;
		} else if (Sex.FEMALE.value.equals(sex)) {
			return Sex.FEMALE;
		} else {
			return Sex.UNKNOWN;
		}
	}
	
	/**
	 * 
	 * 
	 * @param isBorn
	 * @param birthDate
	 * @return
	 */
	public boolean setBirth(boolean isBorn, String birthDate) {
		GedcomValue born = new GedcomValue(false, (isBorn ? YesNo.YES.value : null), 
				"INDIVIDUAL_EVENT_STRUCTURE;BIRT", "BIRT");
		
		GedcomValue date = new GedcomValue(false, birthDate, born, 
				"INDIVIDUAL_EVENT_DETAIL", "EVENT_DETAIL", "DATE");
		
		return apply(born, date);
	}
	
	/**
	 * 
	 * 
	 * @return
	 */
	public boolean isBorn() {
		String born = getValue("INDIVIDUAL_EVENT_STRUCTURE;BIRT", "BIRT");
		
		if (YesNo.YES.value.equals(born)) {
			return true;
		} else {
			return false;
		}
	}
	
	/**
	 * 
	 * 
	 * @return
	 */
	public String getBirthDate() {
		return getValue("INDIVIDUAL_EVENT_STRUCTURE;BIRT", "BIRT", 
				"INDIVIDUAL_EVENT_DETAIL", "EVENT_DETAIL", "DATE");
	}
	
	/**
	 * 
	 * 
	 * @param isDead
	 * @param deathDate
	 * @return
	 */
	public boolean setDeath(boolean isDead, String deathDate) {
		GedcomValue dead = new GedcomValue(false, (isDead ? YesNo.YES.value : null), 
				"INDIVIDUAL_EVENT_STRUCTURE;DEAT", "DEAT");
		
		GedcomValue date = new GedcomValue(false, deathDate, dead, 
				"INDIVIDUAL_EVENT_DETAIL", "EVENT_DETAIL", "DATE");
		
		return apply(dead, date);
	}
	
	/**
	 * 
	 * 
	 * @return
	 */
	public boolean isDead() {
		String born = getValue("INDIVIDUAL_EVENT_STRUCTURE;DEAT", "DEAT");
		
		if (YesNo.YES.value.equals(born)) {
			return true;
		} else {
			return false;
		}
	}
	
	/**
	 * 
	 * 
	 * @return
	 */
	public String getDeathDate() {
		return getValue("INDIVIDUAL_EVENT_STRUCTURE;DEAT", "DEAT", 
				"INDIVIDUAL_EVENT_DETAIL", "EVENT_DETAIL", "DATE");
	}
	
	/**
	 * 
	 * 
	 * @param occupation
	 * @return
	 */
	public boolean setOccupation(String occupation) {
		return apply(new GedcomValue(false, occupation, 
				"INDIVIDUAL_ATTRIBUTE_STRUCTURE;OCCU", "OCCU"));
		
	}
	
	/**
	 * 
	 * 
	 * @return
	 */
	public String getOccupation() {
		return getValue("INDIVIDUAL_ATTRIBUTE_STRUCTURE;OCCU", "OCCU");
	}

	/**
	 * 
	 * 
	 * @param education
	 * @return
	 */
	public boolean setEducation(String education) {
		return apply(new GedcomValue(false, education, 
				"INDIVIDUAL_ATTRIBUTE_STRUCTURE;EDUC", "EDUC"));
		
	}
	
	/**
	 * 
	 * 
	 * @return
	 */
	public String getEducation() {
		return getValue("INDIVIDUAL_ATTRIBUTE_STRUCTURE;EDUC", "EDUC");
	}
	
	/**
	 * 
	 * @param add
	 * @param index
	 * @param name The family/former/married/... name
	 * @param nameType
	 * @param firstNames The name of the individual (first/middle/... name)
	 * @return
	 */
	private boolean setName(boolean add, int index, String name, NameType nameType, String... firstNames) {
		String firstNamesString = GedcomFormatter.makeStringList(
				Arrays.asList(firstNames), ", ", "", "", false, null, false).toString();
		
		String indexString = "";
		
		if (index != -1) {
			indexString = GedcomNode.PATH_OPTION_DELIMITER + index;
		}
		
		GedcomValue n = new GedcomValue(add, firstNamesString + " /" + name + "/", 
				"PERSONAL_NAME_STRUCTURE" + indexString, "NAME");
		
		GedcomValue givn = new GedcomValue(add, firstNamesString, n, 
				"PERSONAL_NAME_PIECES", "GIVN");
		
		GedcomValue surn = new GedcomValue(add, name, n, 
				"PERSONAL_NAME_PIECES", "SURN");
		
		GedcomValue type = new GedcomValue(add, nameType.value, n, 
				"TYPE");
		
		return apply(n, givn, surn, type);
	}
	
	/**
	 * 
	 * 
	 * @param name The family/former/married/... name
	 * @param firstNames The name of the individual (first/middle/... name)
	 * @return
	 */
	public boolean addName(String name, String... firstNames) {
		return addName(name, NameType.UNSPECIFIED, firstNames);
	}
	
	/**
	 * 
	 * 
	 * @param name The family/former/married/... name
	 * @param nameType
	 * @param firstNames The name of the individual (first/middle/... name)
	 * @return
	 */
	public boolean addName(String name, NameType nameType, String... firstNames) {
		return setName(true, -1, name, nameType, firstNames);
	}
	
	/**
	 * Sets the name and if there is no name with the given index, a new name 
	 * block is added
	 * 
	 * @param index
	 * @param name
	 * @param firstNames
	 * @return
	 */
	public boolean setName(int index, String name, String... firstNames) {
		return setName(index, name, NameType.UNSPECIFIED, firstNames);
	}
		
	/**
	 * Sets the name and if there is no name with the given index, a new name 
	 * block is added
	 * 
	 * @param index
	 * @param name
	 * @param nameType
	 * @param firstNames
	 * @return
	 */
	public boolean setName(int index, String name, NameType nameType, String... firstNames) {
		return setName(false, index, name, nameType, firstNames);
	}
	
	/**
	 * name = last name = family name = surname<br>
	 * Family name = surname (at least in western context -> http://en.wikipedia.org/wiki/Family_name)
	 * 
	 * @param index
	 * @return
	 */
	public String getName(int index) {
		return getValue("PERSONAL_NAME_STRUCTURE" + GedcomNode.PATH_OPTION_DELIMITER + index, "NAME");
	}
	
	/**
	 * given name = first name = forename
	 * 
	 * @param index
	 * @return
	 */
	public String getGivenName(int index) {
		return getValue("PERSONAL_NAME_STRUCTURE" + GedcomNode.PATH_OPTION_DELIMITER + index, "NAME", "PERSONAL_NAME_PIECES", "GIVN");
	}
	
	/**
	 * surname = family name = name = last name<br>
	 * Family name = surname (at least in western context -> http://en.wikipedia.org/wiki/Family_name)
	 * 
	 * @param index
	 * @return
	 */
	public String getSurname(int index) {
		return getValue("PERSONAL_NAME_STRUCTURE" + GedcomNode.PATH_OPTION_DELIMITER + index, "NAME", "PERSONAL_NAME_PIECES", "SURN");
	}
	
	/**
	 * 
	 * 
	 * @param index
	 * @return
	 */
	public String getNameType(int index) {
		return getValue("PERSONAL_NAME_STRUCTURE" + GedcomNode.PATH_OPTION_DELIMITER + index, "NAME", "TYPE");
	}
	
	/**
	 * 
	 * <commit_msg>Return the NameType enum for the name type instead of the string<commit_after>/**
 *    Copyright 2013 <NAME> (github.com/thnaeff)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 */
package ch.thn.gedcom.creator;


import java.util.ArrayList;
import java.util.Arrays;

import ch.thn.gedcom.GedcomFormatter;
import ch.thn.gedcom.creator.GedcomCreatorEnums.NameType;
import ch.thn.gedcom.creator.GedcomCreatorEnums.Sex;
import ch.thn.gedcom.creator.GedcomCreatorEnums.YesNo;
import ch.thn.gedcom.data.GedcomNode;
import ch.thn.gedcom.store.GedcomStore;

/**
 * @author <NAME> (github.com/thnaeff)
 *
 */
public class GedcomCreatorIndividual extends GedcomCreatorStructure {
		
	
	/**
	 * An INDIVIDUAL_RECORD
	 * 
	 * @param store
	 * @param id
	 */
	public GedcomCreatorIndividual(GedcomStore store, String id) {
		super(store, "INDIVIDUAL_RECORD", "INDI");
		
		if (!setId(id)) {
			throw new GedcomCreatorError("Failed to create individual with ID " + 
					id + ". Id could not be set.");
		}
	}
	
	/**
	 * 
	 * 
	 * @param store
	 * @param node
	 */
	public GedcomCreatorIndividual(GedcomStore store, GedcomNode node) {
		super(store, "INDIVIDUAL_RECORD", node, "INDI");
	}
	
	/**
	 * 
	 * 
	 * @param id
	 * @return
	 * @throws GedcomCreatorError
	 */
	public boolean setId(String id) {
		if (id == null || id.length() == 0) {
			throw new GedcomCreatorError("Setting an empty ID is not allowed");
		}
		
		return apply(new GedcomXRef(false, id));
	}
	
	/**
	 * 
	 * 
	 * @return
	 */
	public String getId() {
		return getXRef();
	}
	
	/**
	 * 
	 * 
	 * @param sex
	 * @return
	 */
	public boolean setSex(Sex sex) {
		return apply(new GedcomValue(false, sex.value, 
				"SEX"));
	}
	
	/**
	 * 
	 * 
	 * @return
	 */
	public Sex getSex() {
		String sex = getValue("SEX");
		
		if (Sex.MALE.value.equals(sex)) {
			return Sex.MALE;
		} else if (Sex.FEMALE.value.equals(sex)) {
			return Sex.FEMALE;
		} else {
			return Sex.UNKNOWN;
		}
	}
	
	/**
	 * 
	 * 
	 * @param isBorn
	 * @param birthDate
	 * @return
	 */
	public boolean setBirth(boolean isBorn, String birthDate) {
		GedcomValue born = new GedcomValue(false, (isBorn ? YesNo.YES.value : null), 
				"INDIVIDUAL_EVENT_STRUCTURE;BIRT", "BIRT");
		
		GedcomValue date = new GedcomValue(false, birthDate, born, 
				"INDIVIDUAL_EVENT_DETAIL", "EVENT_DETAIL", "DATE");
		
		return apply(born, date);
	}
	
	/**
	 * 
	 * 
	 * @return
	 */
	public boolean isBorn() {
		String born = getValue("INDIVIDUAL_EVENT_STRUCTURE;BIRT", "BIRT");
		
		if (YesNo.YES.value.equals(born)) {
			return true;
		} else {
			return false;
		}
	}
	
	/**
	 * 
	 * 
	 * @return
	 */
	public String getBirthDate() {
		return getValue("INDIVIDUAL_EVENT_STRUCTURE;BIRT", "BIRT", 
				"INDIVIDUAL_EVENT_DETAIL", "EVENT_DETAIL", "DATE");
	}
	
	/**
	 * 
	 * 
	 * @param isDead
	 * @param deathDate
	 * @return
	 */
	public boolean setDeath(boolean isDead, String deathDate) {
		GedcomValue dead = new GedcomValue(false, (isDead ? YesNo.YES.value : null), 
				"INDIVIDUAL_EVENT_STRUCTURE;DEAT", "DEAT");
		
		GedcomValue date = new GedcomValue(false, deathDate, dead, 
				"INDIVIDUAL_EVENT_DETAIL", "EVENT_DETAIL", "DATE");
		
		return apply(dead, date);
	}
	
	/**
	 * 
	 * 
	 * @return
	 */
	public boolean isDead() {
		String born = getValue("INDIVIDUAL_EVENT_STRUCTURE;DEAT", "DEAT");
		
		if (YesNo.YES.value.equals(born)) {
			return true;
		} else {
			return false;
		}
	}
	
	/**
	 * 
	 * 
	 * @return
	 */
	public String getDeathDate() {
		return getValue("INDIVIDUAL_EVENT_STRUCTURE;DEAT", "DEAT", 
				"INDIVIDUAL_EVENT_DETAIL", "EVENT_DETAIL", "DATE");
	}
	
	/**
	 * 
	 * 
	 * @param occupation
	 * @return
	 */
	public boolean setOccupation(String occupation) {
		return apply(new GedcomValue(false, occupation, 
				"INDIVIDUAL_ATTRIBUTE_STRUCTURE;OCCU", "OCCU"));
		
	}
	
	/**
	 * 
	 * 
	 * @return
	 */
	public String getOccupation() {
		return getValue("INDIVIDUAL_ATTRIBUTE_STRUCTURE;OCCU", "OCCU");
	}

	/**
	 * 
	 * 
	 * @param education
	 * @return
	 */
	public boolean setEducation(String education) {
		return apply(new GedcomValue(false, education, 
				"INDIVIDUAL_ATTRIBUTE_STRUCTURE;EDUC", "EDUC"));
		
	}
	
	/**
	 * 
	 * 
	 * @return
	 */
	public String getEducation() {
		return getValue("INDIVIDUAL_ATTRIBUTE_STRUCTURE;EDUC", "EDUC");
	}
	
	/**
	 * 
	 * @param add
	 * @param index
	 * @param name The family/former/married/... name
	 * @param nameType
	 * @param firstNames The name of the individual (first/middle/... name)
	 * @return
	 */
	private boolean setName(boolean add, int index, String name, NameType nameType, String... firstNames) {
		String firstNamesString = GedcomFormatter.makeStringList(
				Arrays.asList(firstNames), ", ", "", "", false, null, false).toString();
		
		String indexString = "";
		
		if (index != -1) {
			indexString = GedcomNode.PATH_OPTION_DELIMITER + index;
		}
		
		GedcomValue n = new GedcomValue(add, firstNamesString + " /" + name + "/", 
				"PERSONAL_NAME_STRUCTURE" + indexString, "NAME");
		
		GedcomValue givn = new GedcomValue(add, firstNamesString, n, 
				"PERSONAL_NAME_PIECES", "GIVN");
		
		GedcomValue surn = new GedcomValue(add, name, n, 
				"PERSONAL_NAME_PIECES", "SURN");
		
		GedcomValue type = new GedcomValue(add, nameType.value, n, 
				"TYPE");
		
		return apply(n, givn, surn, type);
	}
	
	/**
	 * 
	 * 
	 * @param name The family/former/married/... name
	 * @param firstNames The name of the individual (first/middle/... name)
	 * @return
	 */
	public boolean addName(String name, String... firstNames) {
		return addName(name, NameType.UNSPECIFIED, firstNames);
	}
	
	/**
	 * 
	 * 
	 * @param name The family/former/married/... name
	 * @param nameType
	 * @param firstNames The name of the individual (first/middle/... name)
	 * @return
	 */
	public boolean addName(String name, NameType nameType, String... firstNames) {
		return setName(true, -1, name, nameType, firstNames);
	}
	
	/**
	 * Sets the name and if there is no name with the given index, a new name 
	 * block is added
	 * 
	 * @param index
	 * @param name
	 * @param firstNames
	 * @return
	 */
	public boolean setName(int index, String name, String... firstNames) {
		return setName(index, name, NameType.UNSPECIFIED, firstNames);
	}
		
	/**
	 * Sets the name and if there is no name with the given index, a new name 
	 * block is added
	 * 
	 * @param index
	 * @param name
	 * @param nameType
	 * @param firstNames
	 * @return
	 */
	public boolean setName(int index, String name, NameType nameType, String... firstNames) {
		return setName(false, index, name, nameType, firstNames);
	}
	
	/**
	 * name = last name = family name = surname<br>
	 * Family name = surname (at least in western context -> http://en.wikipedia.org/wiki/Family_name)
	 * 
	 * @param index
	 * @return
	 */
	public String getName(int index) {
		return getValue("PERSONAL_NAME_STRUCTURE" + GedcomNode.PATH_OPTION_DELIMITER + index, "NAME");
	}
	
	/**
	 * given name = first name = forename
	 * 
	 * @param index
	 * @return
	 */
	public String getGivenName(int index) {
		return getValue("PERSONAL_NAME_STRUCTURE" + GedcomNode.PATH_OPTION_DELIMITER + index, "NAME", "PERSONAL_NAME_PIECES", "GIVN");
	}
	
	/**
	 * surname = family name = name = last name<br>
	 * Family name = surname (at least in western context -> http://en.wikipedia.org/wiki/Family_name)
	 * 
	 * @param index
	 * @return
	 */
	public String getSurname(int index) {
		return getValue("PERSONAL_NAME_STRUCTURE" + GedcomNode.PATH_OPTION_DELIMITER + index, "NAME", "PERSONAL_NAME_PIECES", "SURN");
	}
	
	/**
	 * 
	 * 
	 * @param index
	 * @return
	 */
	public NameType getNameType(int index) {
		String type = getValue("PERSONAL_NAME_STRUCTURE" + GedcomNode.PATH_OPTION_DELIMITER + index, "NAME", "TYPE");
		
		if (NameType.MAIDEN.value.equals(type)) {
			return NameType.MAIDEN;
		} else if (NameType.MARRIED.value.equals(type)) {
			return NameType.MARRIED;
		} else if (NameType.BIRTH.value.equals(type)) {
			return NameType.BIRTH;
		} else if (NameType.AKA.value.equals(type)) {
			return NameType.AKA;
		} else if (NameType.IMMIGRANT.value.equals(type)) {
			return NameType.IMMIGRANT;
		} else {
			return NameType.UNSPECIFIED;
		}
	}
	
	/**
	 * 
	 * 
{'fraction_non_alphanumeric': 0.1343892204952426, 'fraction_numerical': 0.0013001595650375274, 'mean_word_length': 3.2421659563800453, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6435811', 'n_tokens_mistral': 6687, 'n_tokens_neox': 5791, 'n_words': 1403}