// ***************************************************************************************************************************
// * 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.juneau.config.store;

import static java.nio.file.StandardWatchEventKinds.*;
import static java.nio.file.StandardOpenOption.*;
import static org.apache.juneau.internal.StringUtils.*;

import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import java.nio.charset.*;
import java.nio.file.*;
import java.util.concurrent.*;

import org.apache.juneau.*;
import org.apache.juneau.annotation.*;
import org.apache.juneau.internal.*;

/**
 * Filesystem-based storage location for configuration files.
 *
 * <p>
 * Points to a file system directory containing configuration files.
 */
@ConfigurableContext
public class ConfigFileStore extends ConfigStore {

	//-------------------------------------------------------------------------------------------------------------------
	// Configurable properties
	//-------------------------------------------------------------------------------------------------------------------

	static final String PREFIX = "ConfigFileStore";

	/**
	 * Configuration property:  Local file system directory.
	 *
	 * <h5 class='section'>Property:</h5>
	 * <ul>
	 * 	<li><b>Name:</b>  <js>"ConfigFileStore.directory.s"</js>
	 * 	<li><b>Data type:</b>  <c>String</c>
	 * 	<li><b>Default:</b>  <js>"."</js>
	 * 	<li><b>Methods:</b>
	 * 		<ul>
	 * 			<li class='jm'>{@link ConfigFileStoreBuilder#directory(String)}
	 * 			<li class='jm'>{@link ConfigFileStoreBuilder#directory(File)}
	 * 		</ul>
	 * </ul>
	 *
	 * <h5 class='section'>Description:</h5>
	 * <p>
	 * Identifies the path of the directory containing the configuration files.
	 */
	public static final String FILESTORE_directory = PREFIX + ".directory.s";

	/**
	 * Configuration property:  Charset.
	 *
	 * <h5 class='section'>Property:</h5>
	 * <ul>
	 * 	<li><b>Name:</b>  <js>"ConfigFileStore.charset.s"</js>
	 * 	<li><b>Data type:</b>  {@link Charset}
	 * 	<li><b>Default:</b>  {@link Charset#defaultCharset()}
	 * 	<li><b>Methods:</b>
	 * 		<ul>
	 * 			<li class='jm'>{@link ConfigFileStoreBuilder#charset(String)}
	 * 			<li class='jm'>{@link ConfigFileStoreBuilder#charset(Charset)}
	 * 		</ul>
	 * </ul>
	 *
	 * <h5 class='section'>Description:</h5>
	 * <p>
	 * Identifies the charset of external files.
	 */
	public static final String FILESTORE_charset = PREFIX + ".charset.s";

	/**
	 * Configuration property:  Use watcher.
	 *
	 * <h5 class='section'>Property:</h5>
	 * <ul>
	 * 	<li><b>Name:</b>  <js>"ConfigFileStore.useWatcher.b"</js>
	 * 	<li><b>Data type:</b>  <c>Boolean</c>
	 * 	<li><b>Default:</b>  <jk>false</jk>
	 * 	<li><b>Methods:</b>
	 * 		<ul>
	 * 			<li class='jm'>{@link ConfigFileStoreBuilder#useWatcher()}
	 * 		</ul>
	 * </ul>
	 *
	 * <h5 class='section'>Description:</h5>
	 * <p>
	 * Use a file system watcher for file system changes.
	 *
	 * <ul class='notes'>
	 * 	<li>Calling {@link #close()} on this object closes the watcher.
	 * </ul>
	 */
	public static final String FILESTORE_useWatcher = PREFIX + ".useWatcher.s";

	/**
	 * Configuration property:  Watcher sensitivity.
	 *
	 * <h5 class='section'>Property:</h5>
	 * <ul>
	 * 	<li><b>Name:</b>  <js>"ConfigFileStore.watcherSensitivity.s"</js>
	 * 	<li><b>Data type:</b>  {@link WatcherSensitivity}
	 * 	<li><b>Default:</b>  {@link WatcherSensitivity#MEDIUM}
	 * 	<li><b>Methods:</b>
	 * 		<ul>
	 * 			<li class='jm'>{@link ConfigFileStoreBuilder#watcherSensitivity(WatcherSensitivity)}
	 * 			<li class='jm'>{@link ConfigFileStoreBuilder#watcherSensitivity(String)}
	 * 		</ul>
	 * </ul>
	 *
	 * <h5 class='section'>Description:</h5>
	 * <p>
	 * Determines how frequently the file system is polled for updates.
	 *
	 * <ul class='notes'>
	 * 	<li>This relies on internal Sun packages and may not work on all JVMs.
	 * </ul>
	 */
	public static final String FILESTORE_watcherSensitivity = PREFIX + ".watcherSensitivity.s";

	/**
	 * Configuration property:  Update-on-write.
	 *
	 * <h5 class='section'>Property:</h5>
	 * <ul>
	 * 	<li><b>Name:</b>  <js>"ConfigFileStore.updateOnWrite.b"</js>
	 * 	<li><b>Data type:</b>  <c>Boolean</c>
	 * 	<li><b>Default:</b>  <jk>false</jk>
	 * 	<li><b>Methods:</b>
	 * 		<ul>
	 * 			<li class='jm'>{@link ConfigFileStoreBuilder#updateOnWrite()}
	 * 		</ul>
	 * </ul>
	 *
	 * <h5 class='section'>Description:</h5>
	 * <p>
	 * When enabled, the {@link #update(String, String)} method will be called immediately following
	 * calls to {@link #write(String, String, String)} when the contents are changing.
	 * <br>This allows for more immediate responses to configuration changes on file systems that use
	 * polling watchers.
	 * <br>This may cause double-triggering of {@link ConfigStoreListener ConfigStoreListeners}.
	 */
	public static final String FILESTORE_updateOnWrite = PREFIX + ".updateOnWrite.b";

	/**
	 * Configuration property:  File extensions.
	 *
	 * <h5 class='section'>Property:</h5>
	 * <ul>
	 * 	<li><b>Name:</b>  <js>"ConfigFileStore.extensions.s"</js>
	 * 	<li><b>Data type:</b>  <c>String</c> (comma-delimited list)
	 * 	<li><b>Default:</b>  <jk>"cfg"</jk>
	 * 	<li><b>Methods:</b>
	 * 		<ul>
	 * 			<li class='jm'>{@link ConfigFileStoreBuilder#extensions(String)}
	 * 		</ul>
	 * </ul>
	 *
	 * <h5 class='section'>Description:</h5>
	 * <p>
	 * Defines what file extensions to search for when the config name does not have an extension.
	 */
	public static final String FILESTORE_extensions = PREFIX + ".extensions.s";

	//-------------------------------------------------------------------------------------------------------------------
	// Predefined instances
	//-------------------------------------------------------------------------------------------------------------------

	/** Default file store, all default values.*/
	public static final ConfigFileStore DEFAULT = ConfigFileStore.create().build();


	//-------------------------------------------------------------------------------------------------------------------
	// Instance
	//-------------------------------------------------------------------------------------------------------------------

	/**
	 * Create a new builder for this object.
	 *
	 * @return A new builder for this object.
	 */
	public static ConfigFileStoreBuilder create() {
		return new ConfigFileStoreBuilder();
	}

	@Override /* Context */
	public ConfigFileStoreBuilder builder() {
		return new ConfigFileStoreBuilder(getPropertyStore());
	}

	private final File dir;
	private final Charset charset;
	private final WatcherThread watcher;
	private final boolean updateOnWrite;
	private final ConcurrentHashMap<String,String> cache = new ConcurrentHashMap<>();
	private final ConcurrentHashMap<String,String> nameCache = new ConcurrentHashMap<>();
	private final String[] extensions;

	/**
	 * Constructor.
	 *
	 * @param ps The settings for this content store.
	 */
	protected ConfigFileStore(PropertyStore ps) {
		super(ps);
		try {
			dir = new File(getStringProperty(FILESTORE_directory, ".")).getCanonicalFile();
			dir.mkdirs();
			charset = getProperty(FILESTORE_charset, Charset.class, Charset.defaultCharset());
			updateOnWrite = getBooleanProperty(FILESTORE_updateOnWrite, false);
			extensions = getCdlProperty(FILESTORE_extensions, "cfg");
			WatcherSensitivity ws = getProperty(FILESTORE_watcherSensitivity, WatcherSensitivity.class, WatcherSensitivity.MEDIUM);
			watcher = getBooleanProperty(FILESTORE_useWatcher, false) ? new WatcherThread(dir, ws) : null;
			if (watcher != null)
				watcher.start();

		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	@Override /* ConfigStore */
	public synchronized String read(String name) throws IOException {
		name = resolveName(name);

		Path p = resolveFile(name);
		name = p.getFileName().toString();

		String s = cache.get(name);
		if (s != null)
			return s;

		dir.mkdirs();

		// If file doesn't exist, don't trigger creation.
		if (! Files.exists(p))
			return "";

		boolean isWritable = isWritable(p);
		OpenOption[] oo = isWritable ? new OpenOption[]{READ,WRITE,CREATE} : new OpenOption[]{READ};

		try (FileChannel fc = FileChannel.open(p, oo)) {
			try (FileLock lock = isWritable ? fc.lock() : null) {
				ByteBuffer buf = ByteBuffer.allocate(1024);
				StringBuilder sb = new StringBuilder();
				while (fc.read(buf) != -1) {
					sb.append(charset.decode((ByteBuffer)(buf.flip())));
					buf.clear();
				}
				s = sb.toString();
				cache.put(name, s);
			}
		}

		return cache.get(name);
	}

	@Override /* ConfigStore */
	public synchronized String write(String name, String expectedContents, String newContents) throws IOException {
		name = resolveName(name);

		// This is a no-op.
		if (isEquals(expectedContents, newContents))
			return null;

		dir.mkdirs();

		Path p = resolveFile(name);
		name = p.getFileName().toString();

		boolean exists = Files.exists(p);

		// Don't create the file if we're not going to match.
		if ((!exists) && isNotEmpty(expectedContents))
			return "";

		if (isWritable(p)) {
			if (newContents == null)
				Files.delete(p);
			else {
				try (FileChannel fc = FileChannel.open(p, READ, WRITE, CREATE)) {
					try (FileLock lock = fc.lock()) {
						String currentContents = "";
						if (exists) {
							ByteBuffer buf = ByteBuffer.allocate(1024);
							StringBuilder sb = new StringBuilder();
							while (fc.read(buf) != -1) {
								sb.append(charset.decode((ByteBuffer)(buf.flip())));
								buf.clear();
							}
							currentContents = sb.toString();
						}
						if (expectedContents != null && ! isEquals(currentContents, expectedContents)) {
							if (currentContents == null)
								cache.remove(name);
							else
								cache.put(name, currentContents);
							return currentContents;
						}
						fc.position(0);
						fc.write(charset.encode(newContents));
					}
				}
			}
		}

		if (updateOnWrite)
			update(name, newContents);
		else
			cache.remove(name);  // Invalidate the cache.

		return null;
	}

	@Override /* ConfigStore */
	public synchronized boolean exists(String name) {
		return Files.exists(resolveFile(name));
	}

	private Path resolveFile(String name) {
		return dir.toPath().resolve(resolveName(name));
	}

	@Override
	protected String resolveName(String name) {
		if (! nameCache.containsKey(name)) {
			String n = null;

			// Does file exist as-is?
			if (FileUtils.exists(dir, name))
				n = name;

			// Does name already have an extension?
			if (n == null) {
				for (String ext : extensions) {
					if (FileUtils.hasExtension(name, ext)) {
						n = name;
						break;
					}
				}
			}

			// Find file with the correct extension.
			if (n == null) {
				for (String ext : extensions) {
					if (FileUtils.exists(dir, name + '.' + ext)) {
						n = name + '.' + ext;
						break;
					}
				}
			}

			// If file not found, use the default which is the name with the first extension.
			if (n == null)
				n = extensions.length == 0 ? name : (name + "." + extensions[0]);

			nameCache.put(name, n);
		}
		return nameCache.get(name);
	}

	private synchronized boolean isWritable(Path p) {
		try {
			if (! Files.exists(p)) {
				Files.createDirectories(p.getParent());
				if (! Files.exists(p))
					p.toFile().createNewFile();
			}
		} catch (IOException e) {
			return false;
		}
		return Files.isWritable(p);
	}

	@Override /* ConfigStore */
	public synchronized ConfigFileStore update(String name, String newContents) {
		cache.put(name, newContents);
		super.update(name, newContents);
		return this;
	}

	@Override /* Closeable */
	public synchronized void close() {
		if (watcher != null)
			watcher.interrupt();
	}


	//---------------------------------------------------------------------------------------------
	// WatcherThread
	//---------------------------------------------------------------------------------------------

	final class WatcherThread extends Thread {
		private final WatchService watchService;

		WatcherThread(File dir, WatcherSensitivity s) throws Exception {
			watchService = FileSystems.getDefault().newWatchService();
			WatchEvent.Kind<?>[] kinds = new WatchEvent.Kind[]{ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY};
			WatchEvent.Modifier modifier = lookupModifier(s);
			dir.toPath().register(watchService, kinds, modifier);
		}

		@SuppressWarnings("restriction")
		private WatchEvent.Modifier lookupModifier(WatcherSensitivity s) {
			try {
				switch(s) {
					case LOW: return com.sun.nio.file.SensitivityWatchEventModifier.LOW;
					case MEDIUM: return com.sun.nio.file.SensitivityWatchEventModifier.MEDIUM;
					case HIGH: return com.sun.nio.file.SensitivityWatchEventModifier.HIGH;
				}
			} catch (Exception e) {
				/* Ignore */
			}
			return null;

		}

		@SuppressWarnings("unchecked")
		@Override /* Thread */
		public void run() {
		    try {
				WatchKey key;
				while ((key = watchService.take()) != null) {
				    for (WatchEvent<?> event : key.pollEvents()) {
				        WatchEvent.Kind<?> kind = event.kind();
				        if (kind != OVERFLOW)
				        		ConfigFileStore.this.onFileEvent(((WatchEvent<Path>)event));
				    }
				    if (! key.reset())
				    		break;
				}
			} catch (Exception e) {
				e.printStackTrace();
				throw new RuntimeException(e);
			}
		};

		@Override /* Thread */
		public void interrupt() {
			try {
				watchService.close();
			} catch (IOException e) {
				throw new RuntimeException(e);
			} finally {
				super.interrupt();
			}
		}
	}

	/**
	 * Gets called when the watcher service on this store is triggered with a file system change.
	 *
	 * @param e The file system event.
	 * @throws IOException Thrown by underlying stream.
	 */
	protected synchronized void onFileEvent(WatchEvent<Path> e) throws IOException {
		String fn = e.context().getFileName().toString();

		String oldContents = cache.get(fn);
		cache.remove(fn);
		String newContents = read(fn);
		if (! isEquals(oldContents, newContents)) {
			update(fn, newContents);
		}
	}

	//-----------------------------------------------------------------------------------------------------------------
	// Other methods.
	//-----------------------------------------------------------------------------------------------------------------

	@Override /* Context */
	public ObjectMap toMap() {
		return super.toMap()
			.append("ConfigFileStore", new DefaultFilteringObjectMap()
				.append("charset", charset)
				.append("extensions", extensions)
				.append("updateOnWrite", updateOnWrite)
			);
	}
}
