package gr.uoa.di.web.utils;

import eu.dnetlib.domain.data.Document;
import eu.dnetlib.domain.enabling.Vocabulary;
import eu.dnetlib.domain.functionality.DocumentField;
import eu.dnetlib.domain.functionality.SwitchDocumentField;
import gr.uoa.di.web.utils.bibtex.BibTeX;

import java.util.List;
import java.util.Locale;

import org.apache.log4j.Logger;

public class BibTeXGenerator {

	private static Logger logger = Logger.getLogger(BibTeXGenerator.class);
	
	public static BibTeX generateBibTeX(List<DocumentField> fields, Document document, Vocabulary bibTeXVocabulary) {
		BibTeX bibTeX = new BibTeX();
		
		//Create entry
		List<String> entryValues = document.getMap().get("CobjCategory");
		if (entryValues != null && !entryValues.isEmpty()) {
			String entry = bibTeXVocabulary.getEnglishName(entryValues.get(0));
			if (entry == null) { bibTeX.setEntry("article"); } 
			else { bibTeX.setEntry(entry); }
			
		} else {
			bibTeX.setEntry("article");
		}
		
		bibTeX.setKey(generateBibTeXKey(fields, document));
		
		for (DocumentField field: fields) {			
			if (field instanceof SwitchDocumentField) {
				String conditionField = ((SwitchDocumentField) field).getConditionField();				
				String conditionFieldValue = null;
				
				/* if there is no value in the document for the condition field, consider it 'default' */
				if ( document.getMap().get(conditionField) == null || document.getMap().get(conditionField).isEmpty() ) {
					conditionFieldValue = "default";
					
				} else { //else get the one from the document
					conditionFieldValue = document.getMap().get(conditionField).get(0);
				}
							
				/* in case where there is no field for the given conditionFieldValue 
				 * because this was not part of the configuration use "default". If 
				 * there is no field for "default" just continue   */
				
				if (((SwitchDocumentField) field).getDocumentField(conditionFieldValue) != null ) {
					field = ((SwitchDocumentField) field).getDocumentField(conditionFieldValue);
					
				} else if (((SwitchDocumentField) field).getDocumentField("default") != null) {
					field =  ((SwitchDocumentField) field).getDocumentField("default");
					 
				} else {
					continue;
				}
		}
			
			String fieldDescription = LocaleDescriptionUtil.getFieldDescription(field.getDescriptionMap(), Locale.ENGLISH);
			String value = generate(field.getName(), document);
			if (!value.isEmpty() && !value.equals("\"\"")) {
				bibTeX.getFields().put(fieldDescription, value);
			} 
		}
		
		return bibTeX;
	}
	
	public static String generate(String indexField, Document document) {
		List<String> values = document.getFieldValues(indexField);
		
		if (values == null) return "";
				
		StringBuffer buffer = new StringBuffer();
		buffer.append("\"");
		int i = 0;
		
		for (String value:values) {
			if ( i > 0 ) { buffer.append(" and "); }
			buffer.append(escapeCharacters(value));
			i++;
		}
		
		buffer.append("\"");
		
		return buffer.toString();
	}
	
	public static String escapeCharacters(String value) {
		return value.replace("\"", "\\\"").replace("{", "\\{").replace("}", "\\}").replace("$", "\\$");
	}

	public static String generateBibTeXKey(List<DocumentField> fields, Document document) {
		
		String index4author = null;
		//Get the index field for author BibTeX field
		for ( DocumentField field:fields ) {
			if(field.getDescriptionMap().get(new Locale("en", "GB")) != null) {
				if (field.getDescriptionMap().get(new Locale("en", "GB")).equals("author")) {
					index4author = field.getName();
					break;
				}
			}
		}
		
		StringBuffer buffer = new StringBuffer();

		if (index4author != null) {
			List<String> authornames = document.getFieldValues(index4author);
		
			if (authornames != null && !authornames.isEmpty()) {
				for (String fullname: authornames) {
					String parts[] = fullname.split(",");
					String part = parts[0].replace(" ", "");
					if (authornames.size() > 1){
						if(part.length() > 4){
							buffer.append(part.substring(0, 4));
						} else {
							buffer.append(part);
						}
					} else {
						buffer.append(part);
					}
				}
			}	
		}
	
		//TODO: reconsider following the same procedure as for author to get the index field name
		if (document.getMap().get("publicationyear") != null && !document.getMap().get("publicationyear").isEmpty()) {
			String publicationYear = document.getMap().get("publicationyear").get(0);
			if (publicationYear.length() > 3) {
				buffer.append(publicationYear.substring(publicationYear.length()-2, publicationYear.length()));
			} else {
				buffer.append(publicationYear);
			}					
		}
		
		return buffer.toString();			
		
	}
	
}
