/*
 * Copyright 2011 gitblit.com.
 *
 * Licensed 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 com.gitblit;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Map;
import java.util.Properties;

import com.gitblit.utils.FileUtils;

/**
 * Dynamically loads and reloads a properties file by keeping track of the last
 * modification date.
 *
 * @author James Moger
 *
 */
public class FileSettings extends IStoredSettings {

	protected File propertiesFile;

	private final Properties properties = new Properties();

	private volatile long lastModified;

	private volatile boolean forceReload;

	public FileSettings() {
		super(FileSettings.class);
	}

	public FileSettings(String file) {
		this();
		load(file);
	}

	public void load(String file) {
		this.propertiesFile = new File(file);
	}

	/**
	 * Merges the provided settings into this instance.  This will also
	 * set the target file for this instance IFF it is unset AND the merge
	 * source is also a FileSettings.  This is a little sneaky.
	 */
	@Override
	public void merge(IStoredSettings settings) {
		super.merge(settings);

		// sneaky: set the target file from the merge source
		if (propertiesFile == null && settings instanceof FileSettings) {
			this.propertiesFile = ((FileSettings) settings).propertiesFile;
		}
	}

	/**
	 * Returns a properties object which contains the most recent contents of
	 * the properties file.
	 */
	@Override
	protected synchronized Properties read() {
		if (propertiesFile != null && propertiesFile.exists() && (forceReload || (propertiesFile.lastModified() > lastModified))) {
			FileInputStream is = null;
			try {
				Properties props = new Properties();
				is = new FileInputStream(propertiesFile);
				props.load(is);

				// load properties after we have successfully read file
				properties.clear();
				properties.putAll(props);
				lastModified = propertiesFile.lastModified();
				forceReload = false;
			} catch (FileNotFoundException f) {
				// IGNORE - won't happen because file.exists() check above
			} catch (Throwable t) {
				logger.error("Failed to read " + propertiesFile.getName(), t);
			} finally {
				if (is != null) {
					try {
						is.close();
					} catch (Throwable t) {
						// IGNORE
					}
				}
			}
		}
		return properties;
	}

	@Override
	public boolean saveSettings() {
		String content = FileUtils.readContent(propertiesFile, "\n");
		for (String key : removals) {
			String regex = "(?m)^(" + regExEscape(key) + "\\s*+=\\s*+)"
				    + "(?:[^\r\n\\\\]++|\\\\(?:\r?\n|\r|.))*+$";
			content = content.replaceAll(regex, "");
		}
		removals.clear();

		FileUtils.writeContent(propertiesFile, content);
		// manually set the forceReload flag because not all JVMs support real
		// millisecond resolution of lastModified. (issue-55)
		forceReload = true;
		return true;
	}

	/**
	 * Updates the specified settings in the settings file.
	 */
	@Override
	public synchronized boolean saveSettings(Map<String, String> settings) {
		String content = FileUtils.readContent(propertiesFile, "\n");
		for (Map.Entry<String, String> setting:settings.entrySet()) {
			String regex = "(?m)^(" + regExEscape(setting.getKey()) + "\\s*+=\\s*+)"
				    + "(?:[^\r\n\\\\]++|\\\\(?:\r?\n|\r|.))*+$";
			String oldContent = content;
			content = content.replaceAll(regex, setting.getKey() + " = " + setting.getValue());
			if (content.equals(oldContent)) {
				// did not replace value because it does not exist in the file
				// append new setting to content (issue-85)
				content += "\n" + setting.getKey() + " = " + setting.getValue();
			}
		}
		FileUtils.writeContent(propertiesFile, content);
		// manually set the forceReload flag because not all JVMs support real
		// millisecond resolution of lastModified. (issue-55)
		forceReload = true;
		return true;
	}

	private String regExEscape(String input) {
		return input.replace(".", "\\.").replace("$", "\\$").replace("{", "\\{");
	}

	/**
	 * @return the last modification date of the properties file
	 */
	protected long lastModified() {
		return lastModified;
	}

	/**
	 * @return the state of the force reload flag
	 */
	protected boolean forceReload() {
		return forceReload;
	}

	@Override
	public String toString() {
		return propertiesFile.getAbsolutePath();
	}
}
