/*
 * 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.apache.openmeetings.db.dao.label;

import static org.apache.openmeetings.db.util.ApplicationHelper.ensureApplication;
import static org.apache.openmeetings.util.OpenmeetingsVariables.webAppRootKey;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.InvalidPropertiesFormatException;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.Predicate;
import org.apache.openmeetings.db.dao.IDataProviderDao;
import org.apache.openmeetings.db.entity.label.StringLabel;
import org.apache.openmeetings.util.OmFileHelper;
import org.apache.openmeetings.util.XmlExport;
import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
import org.apache.wicket.util.string.Strings;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.red5.logging.Red5LoggerFactory;
import org.slf4j.Logger;

/**
 *
 * CRUD operations for {@link StringLabel}
 *
 * @author solomax, swagner
 *
 */
public class LabelDao implements IDataProviderDao<StringLabel>{
	private static final Logger log = Red5LoggerFactory.getLogger(LabelDao.class, webAppRootKey);
	private static final String ENTRY_ELEMENT = "entry";
	private static final String KEY_ATTR = "key";
	public static final String APP_RESOURCES_EN = "Application.properties.xml";
	public static final String APP_RESOURCES = "Application_%s.properties.xml";
	public static final LinkedHashMap<Long, Locale> languages = new LinkedHashMap<>(); //TODO hide it and return unmodifiable map
	public static final ConcurrentHashMap<Locale, List<StringLabel>> labelCache = new ConcurrentHashMap<>();
	public static final Set<String> keys = new HashSet<>();
	private static Class<?> APP = null;

	public List<Map<String, Object>> getStrings(Long language_id, int start, int count) {
		List<Map<String, Object>> result = new ArrayList<>();
		for (int i = 0; i < count; ++i) {
			Map<String, Object> map = new HashMap<>();
			map.put("id", start + i);
			map.put("value", getString(start + i, language_id));
			result.add(map);
		}
		return result;
	}

	private static void storeLanguages() throws Exception {
		Document d = XmlExport.createDocument();
		Element r = XmlExport.createRoot(d, "language");
		for (Map.Entry<Long, Locale> e : languages.entrySet()) {
			r.addElement("lang").addAttribute("id", "" + e.getKey()).addAttribute("code", e.getValue().toLanguageTag());
		}
		XmlExport.toXml(getLangFile(), d);
	}

	public static void add(Locale l) throws Exception {
		long id = 0L;
		for (Map.Entry<Long, Locale> e : languages.entrySet()) {
			id = e.getKey();
		}
		languages.put(id + 1, l);
		storeLanguages();
		labelCache.put(l, new ArrayList<StringLabel>());
	}

	public String getString(long fieldValuesId, long langId) {
		return ensureApplication(langId).getOmString(fieldValuesId, langId);
	}

	public String getString(String key, long langId) {
		return ensureApplication(langId).getOmString(key, langId);
	}

	private static File getLangFile() {
		return new File(OmFileHelper.getLanguagesDir(), OmFileHelper.nameOfLanguageFile);
	}

	public static synchronized Class<?> getAppClass() throws ClassNotFoundException {
		if (APP == null) {
			//FIXME HACK to resolve package dependencies
			APP = Class.forName("org.apache.openmeetings.web.app.Application");
		}
		return APP;
	}

	public static void initLanguageMap() {
		SAXReader reader = new SAXReader();
		try {
			getAppClass();
			Document document = reader.read(getLangFile());
			Element root = document.getRootElement();
			languages.clear();
			for (@SuppressWarnings("unchecked")Iterator<Element> it = root.elementIterator("lang"); it.hasNext();) {
				Element item = it.next();
				Long id = Long.valueOf(item.attributeValue("id"));
				String code = item.attributeValue("code");
				if (id == 3L) {
					continue;
				}
				languages.put(id, Locale.forLanguageTag(code));
			}
		} catch (Exception e) {
			log.error("Error while building language map");
		}
	}

	public static String getLabelFileName(Locale l) {
		String name = APP_RESOURCES_EN;
		if (!Locale.ENGLISH.equals(l)) {
			name = String.format(APP_RESOURCES, l.toLanguageTag().replace('-', '_'));
		}
		return name;
	}

	private static void storeLabels(Locale l) throws Exception {
		Document d = XmlExport.createDocument();
		Element r = XmlExport.createRoot(d);
		List<StringLabel> labels = labelCache.get(l);
		for (StringLabel sl : labels) {
			r.addElement(ENTRY_ELEMENT).addAttribute(KEY_ATTR, sl.getKey()).addCDATA(sl.getValue());
		}
		URL u = APP.getResource(getLabelFileName(l));
		XmlExport.toXml(new File(u.toURI()), d);
	}

	public static void upload(Locale l, InputStream is) throws Exception {
		List<StringLabel> labels = getLabels(is);
		URL u = APP.getResource(getLabelFileName(Locale.ENGLISH)); //get the URL of existing resource
		File el = new File(u.toURI());
		File f = new File(el.getParentFile(), getLabelFileName(l));
		if (!f.exists()) {
			f.createNewFile();
		}
		labelCache.put(l, labels);
		storeLabels(l);
	}

	private static List<StringLabel> getLabels(Locale l) {
		List<StringLabel> labels = new ArrayList<>();
		try (InputStream is = APP.getResourceAsStream(getLabelFileName(l))) {
			labels = getLabels(is);
		} catch (Exception e) {
			log.error("Error reading resources document", e);
		}
		return labels;
	}

	private static List<StringLabel> getLabels(InputStream is) throws InvalidPropertiesFormatException, IOException {
		final List<StringLabel> labels = new ArrayList<>();
		Properties props = new Properties();
		props.loadFromXML(is);
		props.forEach((k, v) -> labels.add(new StringLabel((String)k, (String)v)));
		return labels;
	}

	private static List<StringLabel> getLabels(Locale l, final String search) {
		if (!labelCache.containsKey(l)) {
			List<StringLabel> ll = getLabels(l);
			if (ll != null) {
				labelCache.putIfAbsent(l, ll);
			}
		}
		List<StringLabel> result = new ArrayList<>(labelCache.containsKey(l) ? labelCache.get(l) : new ArrayList<StringLabel>());
		if (!Strings.isEmpty(search)) {
			CollectionUtils.filter(result, new Predicate<StringLabel>() {
				@Override
				public boolean evaluate(StringLabel o) {
					return o != null && (o.getKey().contains(search) || o.getValue().contains(search));
				}
			});
		}
		return result;
	}

	@Override
	public StringLabel get(long id) {
		throw new RuntimeException("Should not be used");
	}

	@Override
	public StringLabel get(Long id) {
		throw new RuntimeException("Should not be used");
	}

	@Override
	public List<StringLabel> get(int start, int count) {
		throw new RuntimeException("Should not be used");
	}

	@Override
	public List<StringLabel> get(String search, int start, int count, String order) {
		throw new RuntimeException("Should not be used");
	}

	public List<StringLabel> get(Locale l, final String search, int start, int count, final SortParam<String> sort) {
		List<StringLabel> result = getLabels(l, search);
		if (sort != null) {
			Collections.sort(result, new Comparator<StringLabel>() {
				@Override
				public int compare(StringLabel o1, StringLabel o2) {
					int val = 0;
					if (KEY_ATTR.equals(sort.getProperty())) {
						try {
							int i1 = Integer.parseInt(o1.getKey()), i2 = Integer.parseInt(o2.getKey());
							val = i1 - i2;
						} catch (Exception e) {
							val = o1.getKey().compareTo(o2.getKey());
						}
					} else {
						val = o1.getValue().compareTo(o2.getValue());
					}
					return (sort.isAscending() ? 1 : -1) * val;
				}
			});
		}
		return result.subList(start, start + count > result.size() ? result.size() : start + count);
	}

	@Override
	public long count() {
		throw new RuntimeException("Should not be used");
	}

	@Override
	public long count(String search) {
		throw new RuntimeException("Should not be used");
	}

	public long count(Locale l, final String search) {
		return getLabels(l, search).size();
	}

	@Override
	public StringLabel update(StringLabel entity, Long userId) {
		throw new RuntimeException("Should not be used");
	}

	public StringLabel update(Locale l, StringLabel entity) throws Exception {
		List<StringLabel> labels = labelCache.get(l);
		if (!labels.contains(entity)) {
			labels.add(entity);
			keys.add(entity.getKey());
		}
		storeLabels(l);
		return entity;
	}

	@Override
	public void delete(StringLabel entity, Long userId) {
		throw new RuntimeException("Should not be used");
	}

	public void delete(Locale l, StringLabel entity) throws Exception {
		List<StringLabel> labels = labelCache.get(l);
		if (labels.contains(entity)) {
			labels.remove(entity);
			keys.remove(entity.getKey());
			storeLabels(l);
		}
	}

	public static void delete(Locale l) {
		for (Map.Entry<Long, Locale> e : languages.entrySet()) {
			if (e.getValue().equals(l)) {
				languages.remove(e.getKey());
				break;
			}
		}
		labelCache.remove(l);
		try {
			URL u = APP.getResource(getLabelFileName(l));
			if (u != null) {
				File f = new File(u.toURI());
				if (f.exists()) {
					f.delete();
				}
			}
		} catch (Exception e) {
			log.error("Unexpected error while deleting language", e);
		}
	}
}
