/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.openmeetings.app.data.basic;

import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;

import org.openmeetings.app.OpenmeetingsVariables;
import org.openmeetings.app.data.beans.basic.SearchResult;
import org.openmeetings.app.persistence.beans.lang.FieldLanguage;
import org.openmeetings.app.persistence.beans.lang.Fieldlanguagesvalues;
import org.openmeetings.app.persistence.beans.lang.Fieldvalues;
import org.red5.logging.Red5LoggerFactory;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

/**
 * 
 * @author sebastianwagner
 * 
 */
@Transactional
public class Fieldmanagment {

	private static final Logger log = Red5LoggerFactory.getLogger(
			Fieldmanagment.class, OpenmeetingsVariables.webAppRootKey);

	@PersistenceContext
	private EntityManager em;

	@Autowired
	private FieldLanguageDaoImpl fieldLanguageDaoImpl;

	@Autowired
	private Configurationmanagement cfgManagement;
	
	// Reflect the Reverse Order!!
	public Fieldlanguagesvalues getFieldByIdAndLanguageByNavi(
			Long fieldvalues_id, Long language_id) {
		try {
			if (fieldvalues_id == null) {
				return null;
			}

			TypedQuery<Fieldlanguagesvalues> query = em
					.createQuery("select f from Fieldlanguagesvalues f WHERE f.language_id = :language_id AND f.fieldvalues_id = :fieldvalues_id", Fieldlanguagesvalues.class);
			query.setParameter("fieldvalues_id", fieldvalues_id);
			query.setParameter("language_id", language_id);
			Fieldlanguagesvalues flv = null;
			try {
				flv = performReplace(query.getSingleResult());
			} catch (NoResultException ex) {
			}

			FieldLanguage fieldLanguage = fieldLanguageDaoImpl
					.getFieldLanguageById(language_id);

			log.debug("Getting FieldById for Language "
					+ fieldLanguage.getName());

			// Check for Right To Left Languages
			if (fieldLanguage.getRtl()) {

				log.debug("Language requieres RTL");

				Fieldlanguagesvalues remote = flv;
				Fieldlanguagesvalues toAdd = new Fieldlanguagesvalues();
				toAdd.setFieldlanguagesvalues_id(remote
						.getFieldlanguagesvalues_id());
				toAdd.setFieldvalues_id(remote.getFieldvalues_id());
				toAdd.setLanguage_id(remote.getLanguage_id());

				String[] splitted = remote.getValue().split(" ");
				String reverseOrder = "";
				for (int i = splitted.length - 1; i >= 0; i--) {
					reverseOrder += splitted[i];
					if (splitted.length != 1) {
						reverseOrder += " ";
					}
				}
				toAdd.setValue(reverseOrder);

				return toAdd;
			} else {
				log.debug("Language doesnt requiere RTL");

				return flv;
			}

		} catch (Exception ex2) {
			log.error("[getFieldByIdAndLanguage]: ", ex2);
		}
		return null;
	}

	public String getString(Long fieldvalues_id, Long language_id) {
		String result = null;
		Fieldlanguagesvalues flv = getFieldByIdAndLanguage(fieldvalues_id, language_id);
		if (flv != null) {
			result = performReplace(flv).getValue();
		}
		return result;
	}
	
	public Fieldlanguagesvalues getFieldByIdAndLanguage(Long fieldvalues_id,
			Long language_id) {
		try {

			String hql = "select f from Fieldlanguagesvalues as f "
					+ "WHERE f.language_id = :language_id "
					+ "AND f.fieldvalues_id = :fieldvalues_id";

			Fieldlanguagesvalues flv = null;

			TypedQuery<Fieldlanguagesvalues> query = em.createQuery(hql, Fieldlanguagesvalues.class);

			query.setParameter("fieldvalues_id", fieldvalues_id);
			query.setParameter("language_id", language_id);
			List<Fieldlanguagesvalues> fList = query.getResultList();

			if (fList.size() > 0) {
				flv = fList.get(0); //replace should not be performed here to enable string editing via admin
			}

			return flv;
		} catch (Exception ex2) {
			log.error("[getFieldByIdAndLanguage]: ", ex2);
		}
		return null;
	}

	public Long deleteFieldlanguagesvaluesById(Long fieldlanguagesvalues_id) {
		try {
			Fieldlanguagesvalues flv = this
					.getFieldlanguagesvaluesById(fieldlanguagesvalues_id);
			if (flv == null) {
				return new Long(-27);
			}

			flv = em.find(Fieldlanguagesvalues.class, fieldlanguagesvalues_id);

			return new Long(-28);
		} catch (Exception ex2) {
			log.error("[getFieldByIdAndLanguage]: ", ex2);
		}
		return new Long(-1);
	}

	public List<Fieldlanguagesvalues> getAllFieldsByLanguage(Long language_id) {
		try {

			TypedQuery<Fieldlanguagesvalues> query = em
					.createQuery("select f from Fieldlanguagesvalues f WHERE f.language_id = :language_id ", Fieldlanguagesvalues.class);
			query.setParameter("language_id", language_id);
			List<Fieldlanguagesvalues> returnList = performReplace(query.getResultList());

			return returnList;
		} catch (Exception ex2) {
			log.error("[getConfKey]: " + ex2);
		}
		return null;
	}

	public List<Map<String, Object>> getLabelsByLanguage(Long language_id,
			int start, int max) {
		try {

			String sql = "select f from Fieldlanguagesvalues as f "
					+ "WHERE f.language_id = :language_id "
					+ "AND f.fieldvalues_id >= :start AND f.fieldvalues_id <  :max";

			TypedQuery<Fieldlanguagesvalues> query = em.createQuery(sql, Fieldlanguagesvalues.class);
			query.setParameter("language_id", language_id);
			query.setParameter("start", new Long(start));
			query.setParameter("max", new Long(start + max));

			String appName = cfgManagement.getAppName();
			List<Map<String, Object>> returnList = new LinkedList<Map<String, Object>>();
			for (Fieldlanguagesvalues fl : query.getResultList()) {
				Map<String, Object> map = new HashMap<String, Object>();
				map.put("id", fl.getFieldvalues().getFieldvalues_id());
				map.put("value", performReplace(fl.getValue(), appName));
				returnList.add(map);
			}
			FieldLanguage fieldLanguage = fieldLanguageDaoImpl
					.getFieldLanguageById(language_id);

			log.debug("Getting Labels for Language " + fieldLanguage.getName());

			// Check for Right To Left Languages
			if (fieldLanguage.getRtl()) {
				log.debug("Language requieres RTL!");

				List<Map<String, Object>> returnRtlList = new LinkedList<Map<String, Object>>();

				for (Iterator<Map<String, Object>> iter = returnList.iterator(); iter
						.hasNext();) {
					Map<String, Object> remote = iter.next();

					Map<String, Object> toAdd = new HashMap<String, Object>();
					toAdd.put("id", remote.get("id"));

					String value = remote.get("value").toString();

					String[] splitted = value.split(" ");
					String reverseOrder = "";
					for (int i = splitted.length - 1; i >= 0; i--) {
						reverseOrder += splitted[i];
						if (splitted.length != 1) {
							reverseOrder += " ";
						}
					}
					log.debug("reverseOrder " + reverseOrder);
					toAdd.put("value", value);

					returnRtlList.add(toAdd);
				}

				return returnRtlList;
			} else {
				log.debug("Language doesnt requiere RTL!");

				return returnList;

			}

		} catch (Exception ex2) {
			log.error("[getLabelsByLanguage]: ", ex2);
			ex2.printStackTrace();
		}
		return null;
	}

	public List<Fieldlanguagesvalues> getAllFieldsByLanguage(Long language_id,
			int start, int max) {
		try {

			String sql = "select f from Fieldlanguagesvalues f WHERE f.language_id = :language_id "
					+ "AND f.fieldvalues_id >= :start AND f.fieldvalues_id <  :max";

			TypedQuery<Fieldlanguagesvalues> query = em.createQuery(sql, Fieldlanguagesvalues.class);
			query.setParameter("language_id", language_id);
			query.setParameter("start", start);
			query.setParameter("max", start + max);

			List<Fieldlanguagesvalues> returnList = performReplace(query.getResultList());
			FieldLanguage fieldLanguage = fieldLanguageDaoImpl
					.getFieldLanguageById(language_id);

			log.debug("GEtting all fields by language : "
					+ fieldLanguage.getName());

			// Check for Right To Left Languages
			if (fieldLanguage.getRtl()) {
				log.debug("language : " + fieldLanguage.getName()
						+ " requieres RTL");

				List<Fieldlanguagesvalues> returnRtlList = new LinkedList<Fieldlanguagesvalues>();

				for (Iterator<Fieldlanguagesvalues> iter = returnList
						.iterator(); iter.hasNext();) {
					Fieldlanguagesvalues remote = iter.next();
					Fieldlanguagesvalues toAdd = new Fieldlanguagesvalues();
					toAdd.setFieldlanguagesvalues_id(remote
							.getFieldlanguagesvalues_id());
					toAdd.setFieldvalues_id(remote.getFieldvalues_id());
					toAdd.setLanguage_id(remote.getLanguage_id());

					String[] splitted = remote.getValue().split(" ");
					String reverseOrder = "";
					for (int i = splitted.length - 1; i >= 0; i--) {
						reverseOrder += splitted[i];
						if (splitted.length != 1) {
							reverseOrder += " ";
						}
					}
					toAdd.setValue(reverseOrder);

					returnRtlList.add(toAdd);
				}

				return returnRtlList;
			} else {
				log.debug("language : " + fieldLanguage.getName()
						+ " requieres NO RTL");

				return returnList;

			}

		} catch (Exception ex2) {
			log.error("[getConfKey]: ", ex2);
		}
		return null;
	}

	public Long addFieldValueByFieldAndLanguage(Fieldvalues fv,
			Long language_id, String fieldvalue) {
		try {

			Fieldlanguagesvalues flv = new Fieldlanguagesvalues();
			flv.setStarttime(new Date());
			flv.setValue(fieldvalue);
			flv.setLanguage_id(language_id);
			flv.setFieldvalues(fv);
			flv.setDeleted("false");

			flv = em.merge(flv);
			Long fieldlanguagesvaluesId = flv.getFieldlanguagesvalues_id();

			return fieldlanguagesvaluesId;
		} catch (Exception ex2) {
			log.error("[getConfKey]: ", ex2);
		}
		return null;
	}

	public void updateFieldValueByFieldAndLanguage(Fieldlanguagesvalues flv) {
		try {

			if (flv.getFieldlanguagesvalues_id() == null) {
				em.persist(flv);
			} else {
				if (!em.contains(flv)) {
					em.merge(flv);
				}
			}

		} catch (Exception ex2) {
			log.error("[updateFieldValueByFieldAndLanguage]: ", ex2);
		}

	}

	public Fieldvalues addField(String fieldName) {
		try {
			Fieldvalues fl = new Fieldvalues();
			fl.setStarttime(new Date());
			fl.setName(fieldName);
			fl.setDeleted("false");

			fl = em.merge(fl);

			return fl;
		} catch (Exception ex2) {
			log.error("[getConfKey]: ", ex2);
		}
		return null;
	}

	public Long addFieldById(String fieldName, Long fieldvalues_id) {
		try {

			Fieldvalues fl = new Fieldvalues();
			fl.setFieldvalues_id(fieldvalues_id);
			fl.setStarttime(new Date());
			fl.setName(fieldName);
			fl.setDeleted("false");

			fl = em.merge(fl);
			Long fieldId = fl.getFieldvalues_id();

			return fieldId;
		} catch (Exception ex2) {
			log.error("[getConfKey]: ", ex2);
		}
		return null;
	}

	public List<Fieldlanguagesvalues> getMixedFieldValuesList(Long language_id) {
		// all Fieldlanguagesvalues in current Language
		TypedQuery<Fieldlanguagesvalues> q = em.createNamedQuery("allFieldLanguageValues", Fieldlanguagesvalues.class);
		q.setParameter("language_id", language_id);
		return q.getResultList();
	}

	public List<Fieldlanguagesvalues> getUntranslatedFieldValuesList(Long language_id) {
		// all FieldValuesIds in current Language
		TypedQuery<Long> q0 = em.createNamedQuery("allFieldValuesIds", Long.class);
		q0.setParameter("language_id", language_id);
		List<Long> translatedIds = q0.getResultList();
		
		// all not translated values from english
		TypedQuery<Fieldlanguagesvalues> q1 = em.createNamedQuery("allNotTranslatedValues", Fieldlanguagesvalues.class);
		q1.setParameter("id_list", translatedIds);

		return q1.getResultList();
	}

	public Fieldvalues getFieldvaluesById(Long fieldvalues_id, Long language_id) {
		try {
			// log.error("Long fieldvalues_id, Long language_id "+fieldvalues_id+" || "+language_id);
			Fieldvalues fv = this.getFieldvaluesById(fieldvalues_id);
			fv.setFieldlanguagesvalue(this.getFieldByIdAndLanguage(
					fieldvalues_id, language_id));
			return fv;
		} catch (Exception e) {
			log.error("[getFieldvaluesById] ", e);
		}
		return null;
	}

	/**
	 * update given Field and its Label by IDs
	 * 
	 * @param fieldvalues_id
	 * @param name
	 * @param fieldlanguagesvalues_id
	 * @param value
	 * @return
	 */
	public Long updateLabel(Long fieldvalues_id, String name,
			Long fieldlanguagesvalues_id, String value) {
		try {
			Fieldvalues fv = this.getFieldvaluesById(fieldvalues_id);
			if (fv == null) {
				return new Long(-24);
			} else {
				fv.setName(name);
				fv.setUpdatetime(new Date());
				this.updateField(fv);
			}
			Fieldlanguagesvalues flv = this
					.getFieldlanguagesvaluesById(fieldlanguagesvalues_id);
			if (flv == null) {
				return new Long(-25);
			} else {
				flv.setUpdatetime(new Date());
				flv.setValue(value);
				this.updateFieldLanguagesLabel(flv);
			}
			return fieldvalues_id;
		} catch (Exception ex2) {
			log.error("[updateFieldLanguagesLabel]: ", ex2);
		}
		return new Long(-1);
	}

	public Long addAndUpdateLabel(Long fieldvalues_id, String name,
			String value, Long language_id) {
		try {
			Fieldvalues fv = this.getFieldvaluesById(fieldvalues_id);
			if (fv == null) {
				return new Long(-24);
			} else {
				fv.setName(name);
				fv.setUpdatetime(new Date());
				this.updateField(fv);
			}
			this.addFieldValueByFieldAndLanguage(fv, language_id,
					value);
			return fieldvalues_id;
		} catch (Exception ex2) {
			log.error("[updateFieldLanguagesLabel]: ", ex2);
		}
		return new Long(-1);
	}

	public Long addFieldAndLabel(String name, String value, Long language_id) {
		try {
			Fieldvalues fv = addField(name);
			if (fv.getFieldvalues_id() > 0) {
				this.addFieldValueByFieldAndLanguage(fv,
						language_id, value);
				return fv.getFieldvalues_id();
			} else {
				return -1L;
			}
		} catch (Exception ex2) {
			log.error("[updateFieldLanguagesLabel]: ", ex2);
		}
		return -1L;
	}

	public SearchResult<Fieldvalues> getFieldsByLanguage(int start, int max, String orderby,
			boolean asc, Long language_id, String search) {
		try {
			SearchResult<Fieldvalues> sresult = new SearchResult<Fieldvalues>();
			sresult.setObjectName(Fieldlanguagesvalues.class.getName());
			sresult.setRecords(this.selectMaxFromFieldsValues(search));
			sresult.setResult(this.getMixedFieldValuesList(start, max, orderby,
					asc, language_id, search));
			return sresult;
		} catch (Exception ex2) {
			log.error("[getFieldsByLanguage]: ", ex2);
		}
		return null;
	}

	private Long selectMaxFromFieldsValues(String search) throws Exception {
		String queryLanguage = "select count(c.fieldvalues_id) from Fieldvalues c where c.deleted = 'false'";
		if (search.length()>0) {
			queryLanguage += " AND (c.name LIKE :searchStr " +
							"OR c.fieldvalues_id = :fieldvalues_id)";
		}
		TypedQuery<Long> query = em
				.createQuery(queryLanguage, Long.class);
		if (search.length()>0) {
			query.setParameter("searchStr", "%"+search+"%");
			long idNumber = 0;
			try {
				idNumber = Long.parseLong(search);
			} catch (NumberFormatException nfe) {
			}
			query.setParameter("fieldvalues_id", idNumber);
		}
		return query.getResultList().get(0);
	}

	private List<Fieldvalues> getMixedFieldValuesList(int start, int max,
			String orderby, boolean asc, Long language_id, String search) throws Exception {
		List<Fieldvalues> fvList = this.getFieldsValues(start, max, orderby, asc, search);
		for (Fieldvalues fv : fvList) {
			fv.setFieldlanguagesvalue(this.getFieldByIdAndLanguage(
					fv.getFieldvalues_id(), language_id));
		}
		return fvList;
	}

	private List<Fieldvalues> getFieldsValues(int start, int max,
			String orderby, boolean asc, String search) throws Exception {
		String queryLanguage = "select c from Fieldvalues c where c.deleted = 'false'";
		if (search.length()>0) {
			queryLanguage += " AND (c.name LIKE :searchStr " +
							"OR c.fieldvalues_id = :fieldvalues_id)";
		}
		if (asc) {
			queryLanguage += " ORDER BY "+orderby+ " ASC";
		} else {
			queryLanguage += " ORDER BY "+orderby + "DESC";
		}
		TypedQuery<Fieldvalues> q = em
				.createQuery(queryLanguage, Fieldvalues.class);
		if (search.length()>0) {
			q.setParameter("searchStr", "%"+search+"%");
			long idNumber = 0;
			try {
				idNumber = Long.parseLong(search);
			} catch (NumberFormatException nfe) {
			}
			q.setParameter("fieldvalues_id", idNumber);
		}
		q.setFirstResult(start);
		q.setMaxResults(max);
		return  q.getResultList();
	}

	public Fieldvalues getFieldvaluesById(Long fieldvalues_id) {
		String hql = "select f from Fieldvalues f WHERE f.fieldvalues_id = :fieldvalues_id ";
		TypedQuery<Fieldvalues> query = em.createQuery(hql, Fieldvalues.class);
		query.setParameter("fieldvalues_id", fieldvalues_id);
		Fieldvalues fv = null;
		try {
			fv = query.getSingleResult();
		} catch (NoResultException ex) {
		}
		return fv;
	}

	private Fieldlanguagesvalues getFieldlanguagesvaluesById(
			Long fieldlanguagesvalues_id) throws Exception {
		String hql = "select f from Fieldlanguagesvalues f WHERE f.fieldlanguagesvalues_id = :fieldlanguagesvalues_id ";
		TypedQuery<Fieldlanguagesvalues> query = em.createQuery(hql, Fieldlanguagesvalues.class);
		query.setParameter("fieldlanguagesvalues_id", fieldlanguagesvalues_id);
		Fieldlanguagesvalues flv = null;
		try {
			flv = performReplace(query.getSingleResult());
		} catch (NoResultException ex) {
		}
		return flv;
	}
	
	private Fieldlanguagesvalues performReplace(Fieldlanguagesvalues f) {
		String appName = cfgManagement.getAppName();
		return performReplace(f, appName);
	}
	
	private String performReplace(String val, String appName) {
		return val.replaceAll("\\$APP_NAME", appName);
	}
	
	private Fieldlanguagesvalues performReplace(Fieldlanguagesvalues f, String appName) {
		Fieldlanguagesvalues r = new Fieldlanguagesvalues();
		r.setDeleted(f.getDeleted());
		r.setFieldlanguagesvalues_id(f.getFieldlanguagesvalues_id());
		r.setFieldvalues_id(f.getFieldvalues_id());
		r.setLanguage_id(f.getLanguage_id());
		r.setStarttime(f.getStarttime());
		r.setUpdatetime(f.getUpdatetime());
		r.setValue(performReplace(f.getValue(), appName));
		return r;
	}
	
	private <T extends Collection<Fieldlanguagesvalues>> T performReplace(T flv) {
		String appName = cfgManagement.getAppName();
		
		for (Fieldlanguagesvalues f : flv) {
			performReplace(f, appName);
		}
		return flv;
	}
	
	private void updateField(Fieldvalues fv) throws Exception {
		if (fv.getFieldvalues_id() == null) {
			em.persist(fv);
		} else {
			if (!em.contains(fv)) {
				em.merge(fv);
			}
		}
	}

	private void updateFieldLanguagesLabel(Fieldlanguagesvalues flv)
			throws Exception {
		if (flv.getFieldlanguagesvalues_id() == null) {
			em.persist(flv);
		} else {
			if (!em.contains(flv)) {
				em.merge(flv);
			}
		}
	}

}
