package data;

import static gui.Messages.*;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;

import gui.I18N;
import javafx.collections.FXCollections;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import data.Enums.solar.SolarFilters;
import gui.ValidationUtil;
import javafx.collections.ObservableList;

public class Corpus {
	public final static Logger logger = LogManager.getLogger(Corpus.class);

	private CorpusType corpusType;
	private File chosenResultsLocation;
	private File chosenCorpusLocation;
	private Collection<File> detectedCorpusFiles;
	boolean headerRead;
	private ArrayList<Taxonomy> taxonomy; // if gigafida or gos
	private Taxonomy taxonomyTotal;
	private HashMap<String, ObservableList<String>> solarFilters; // if solar
	public HashMap<String, ObservableList<String>> solarSelectedFilters; // if solar selected
	private HashMap<String, HashSet<String>> solarFiltersForXML; // if solar - used while parsing xml
	private boolean gosOrthMode;
	private ArrayList<String> validationErrors;
	private String corpusName = "";
	private String punctuation = "punctuation.COMMA";

	public Corpus() {
		validationErrors = new ArrayList<>();
		setTotal();
	}

	public String getCorpusName() {
		return corpusName;
	}

	public void setCorpusName(String corpusName) {
		this.corpusName = corpusName;
		logger.info("Corpus.set: ", corpusName);
	}

	public String getPunctuation() {
		return punctuation;
	}

	public void setPunctuation(String punctuation) {
		this.punctuation = punctuation;
		logger.info("Punctuation.set: ", punctuation);
	}

	public CorpusType getCorpusType() {
		return corpusType;
	}

	public void setCorpusType(CorpusType corpusType) {
		this.corpusType = corpusType;
		logger.info("Corpus.set: ", corpusType);
	}

	public File getChosenResultsLocation() {
		return chosenResultsLocation;
	}

	public void setChosenResultsLocation(File chosenResultsLocation) {
		this.chosenResultsLocation = chosenResultsLocation;
		logger.info("Corpus.set: ", chosenResultsLocation);
	}

	public File getChosenCorpusLocation() {
		return chosenCorpusLocation;
	}

	public void setChosenCorpusLocation(File chosenCorpusLocation) {
		this.chosenCorpusLocation = chosenCorpusLocation;
		logger.info("Corpus.set: ", chosenCorpusLocation);
	}

	public Collection<File> getDetectedCorpusFiles() {
		return detectedCorpusFiles;
	}

	public void setDetectedCorpusFiles(Collection<File> detectedCorpusFiles) {
		this.detectedCorpusFiles = detectedCorpusFiles;
		logger.info("Corpus.set: ", detectedCorpusFiles);
	}

	public void setHeaderRead(boolean headerRead) {
		this.headerRead = headerRead;
	}

	public Taxonomy getTotal() {
		return taxonomyTotal;
	}

	public void setTotal() {
		taxonomyTotal = new Taxonomy("Total", false);
	}

	public ArrayList<Taxonomy> getTaxonomy() {
		return taxonomy;
	}

	public ObservableList<String> getObservableListTaxonomy() {
		ArrayList<String> al = new ArrayList<>();
		if(taxonomy != null) {
			for (Taxonomy t : this.taxonomy) {
				al.add(t.toLongNameString());
			}
		}
		return FXCollections.observableArrayList(al);
	}

	public void setTaxonomy(ObservableList<String> taxonomy) {
		this.taxonomy = new ArrayList<>();
		for(String t : taxonomy){
			this.taxonomy.add(new Taxonomy(t, true));
		}
		logger.info("Corpus.set: ", taxonomy);
	}

	public HashMap<String, ObservableList<String>> getSolarFilters() {
		return solarFilters;
	}

	public void setSolarFilters(HashMap<String, ObservableList<String>> solarFilters) {
		this.solarFilters = solarFilters;
		logger.info("Corpus.set: ", solarFilters);
	}

	public HashMap<String, ObservableList<String>> getSolarSelectedFilters() {
		return solarSelectedFilters;
	}

	public void setSolarFiltersForXML(HashMap<String, HashSet<String>> solarFiltersForXML) {
		this.solarFiltersForXML = solarFiltersForXML;
		logger.info("Corpus.set: ", solarFiltersForXML);
	}

	public boolean isGosOrthMode() {
		return gosOrthMode;
	}

	public String getValidationErrorsToString() {
		return StringUtils.join(validationErrors, "\n - ");
	}

	public boolean validate() {
		if (corpusType == null) {
			validationErrors.add(I18N.get("message.LABEL_RESULTS_CORPUS_TYPE_NOT_SET"));
		}

		if (chosenCorpusLocation == null) {
			validationErrors.add(I18N.get("message.LABEL_CORPUS_LOCATION_NOT_SET"));
		}

		if (chosenResultsLocation == null) {
			validationErrors.add(I18N.get("message.LABEL_RESULTS_LOCATION_NOT_SET"));
		}

		if (!headerRead && corpusType != null) {
			// if user didn't opt into reading the headers, set default taxonomy or solar filters
			if (Tax.getCorpusTypesWithTaxonomy().contains(corpusType)) {
				Tax.getTaxonomyForComboBox(corpusType);
				setTaxonomy(Tax.getTaxonomyForComboBox(corpusType));
			} else if (corpusType == CorpusType.SOLAR && solarFilters == null) {
				setSolarFilters(SolarFilters.getFiltersForComboBoxes());
			}
		}

		if (headerRead && ValidationUtil.isEmpty(taxonomy)) {
			// mustn't happen, intercept at gui level
		}

		if (!ValidationUtil.isEmpty(validationErrors)) {
			logger.error("Corpus validation error: ", StringUtils.join(validationErrors, "\n - "));
			return false;
		} else {
			return true;
		}
	}
}
