/*
 * This file is part of Nuts Framework.
 * Copyright(C) 2009-2012 Nuts Develop Team.
 *
 * Nuts Framework is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License any later version.
 *
 * Nuts Framework is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Nuts Framework. If not, see <http://www.gnu.org/licenses/>.
 */
package nuts.core.io;

import nuts.core.bind.json.Jsons;
import nuts.core.lang.Strings;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.vfs2.FileObject;


/**
 * Properties extents class.
 */
@SuppressWarnings("serial")
public class PropertiesEx extends Properties {

	/**
	 * @param file file
	 * @param props properties
	 * @throws IOException if an IO error occurs
	 */
	public static void load(Properties props, File file) throws IOException {
		InputStream is = null;
		try {
			is = new FileInputStream(file);
			props.load(is);
		}
		finally {
			Streams.safeClose(is);
		}
	}

	/**
	 * @param file file
	 * @param props properties
	 * @throws IOException if an IO error occurs
	 */
	public static void load(Properties props, FileObject file) throws IOException {
		InputStream is = null;
		try {
			is = file.getContent().getInputStream();
			props.load(is);
		}
		finally {
			Streams.safeClose(is);
		}
	}

	/**
	 * @param file file
	 * @throws IOException if an IO error occurs
	 */
	public void load(File file) throws IOException {
		load(this, file);
	}

	/**
	 * @param file file
	 * @throws IOException if an IO error occurs
	 */
	public void load(FileObject file) throws IOException {
		load(this, file);
	}

	/**
	 * @param key key
	 * @return the property
	 */
	public boolean getPropertyAsBoolean(String key) {
		return getPropertyAsBoolean(key, false);
	}

	/**
	 * @param key key
	 * @return the property
	 */
	public boolean getPropertyAsBoolean(String key, boolean defv) {
		String v = Strings.stripToNull(getProperty(key));
		if (Strings.isEmpty(v)) {
			return defv;
		}
		return Boolean.parseBoolean(v);
	}

	/**
	 * @param key key
	 * @return the property
	 */
	public int getPropertyAsInt(String key) {
		return getPropertyAsInt(key, 0);
	}

	/**
	 * @param key key
	 * @return the property
	 */
	public int getPropertyAsInt(String key, int defaultVar) {
		try {
			return Integer.parseInt(getProperty(key));
		}
		catch (NumberFormatException e) {
			return defaultVar;
		}
	}

	/**
	 * @param key key
	 * @return the property
	 */
	public long getPropertyAsLong(String key) {
		return getPropertyAsLong(key, 0L);
	}

	/**
	 * @param key key
	 * @return the property
	 */
	public Long getPropertyAsLong(String key, long defaultVar) {
		try {
			return Long.parseLong(getProperty(key));
		}
		catch (NumberFormatException e) {
			return defaultVar;
		}
	}

	/**
	 * getPropertyAsList
	 * @param name resource name
	 * @return List value
	 */
	public List getPropertyAsList(String name) {
		return getPropertyAsList(name, null);
	}
	
	/**
	 * getPropertyAsList
	 * @param name resource name
	 * @param defaultValue default value
	 * @return list value
	 */
	public List getPropertyAsList(String name, List defaultValue) {
		List list = defaultValue;

		String expr = getProperty(name);
		if (Strings.isNotEmpty(expr)) {
			expr = Strings.strip(expr);
			if (!expr.startsWith("[") || !expr.endsWith("]")) {
				expr = "[" + expr + "]";
			}

			String em = "Invalid json array expression: "
				+ name + " - " + expr;

			list = Jsons.fromJson(expr, ArrayList.class);
			if (list == null) {
				throw new RuntimeException(em);
			}
		}

		return list;
	}

	/**
	 * @param name resource name
	 * @return map value
	 */
	public Map getPropertyAsMap(String name) {
		return getPropertyAsMap(name, null);
	}
	
	/**
	 * @param name resource name
	 * @param defaultValue default value
	 * @return map value
	 */
	public Map getPropertyAsMap(String name, Map defaultValue) {
		Map map = defaultValue;

		String expr = getProperty(name);
		if (Strings.isNotEmpty(expr)) {
			expr = Strings.strip(expr);
			if (!expr.startsWith("{") || !expr.endsWith("}")) {
				expr = "{" + expr + "}";
			}

			String em = "Invalid json object expression: "
				+ name + " - " + expr;
			map = Jsons.fromJson(expr, LinkedHashMap.class);
			if (map == null) {
				throw new RuntimeException(em);
			}
		}

		return map;
	}
}
