/*
 * Copyright (C) 2009, Google Inc.
 * Copyright (C) 2009, Robin Rosenberg <robin.rosenberg@dewire.com>
 * Copyright (C) 2009, Yann Simon <yann.simon.fr@gmail.com> and others
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Distribution License v. 1.0 which is available at
 * https://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

package org.eclipse.jgit.junit;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
import java.util.concurrent.TimeUnit;

import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.SystemReader;
import org.eclipse.jgit.util.time.MonotonicClock;
import org.eclipse.jgit.util.time.ProposedTimestamp;

/**
 * Mock {@link org.eclipse.jgit.util.SystemReader} for tests.
 */
public class MockSystemReader extends SystemReader {
	private static final class MockConfig extends FileBasedConfig {
		private MockConfig(File cfgLocation, FS fs) {
			super(cfgLocation, fs);
		}

		@Override
		public void load() throws IOException, ConfigInvalidException {
			// Do nothing
		}

		@Override
		public void save() throws IOException {
			// Do nothing
		}

		@Override
		public boolean isOutdated() {
			return false;
		}

		@Override
		public String toString() {
			return "MockConfig";
		}
	}

	long now = 1250379778668L; // Sat Aug 15 20:12:58 GMT-03:30 2009

	final Map<String, String> values = new HashMap<>();

	private FileBasedConfig userGitConfig;

	private FileBasedConfig jgitConfig;

	FileBasedConfig systemGitConfig;

	/**
	 * Set the user-level git config
	 *
	 * @param userGitConfig
	 *            set another user-level git config
	 * @return the old user-level git config
	 * @since 5.1.9
	 */
	public FileBasedConfig setUserGitConfig(FileBasedConfig userGitConfig) {
		FileBasedConfig old = this.userGitConfig;
		this.userGitConfig = userGitConfig;
		return old;
	}

	/**
	 * Set the jgit config stored at $XDG_CONFIG_HOME/jgit/config
	 *
	 * @param jgitConfig
	 *            set the jgit configuration
	 * @since 5.5
	 */
	public void setJGitConfig(FileBasedConfig jgitConfig) {
		this.jgitConfig = jgitConfig;
	}

	/**
	 * Set the system-level git config
	 *
	 * @param systemGitConfig
	 *            the new system-level git config
	 * @return the old system-level config
	 * @since 5.1.9
	 */
	public FileBasedConfig setSystemGitConfig(FileBasedConfig systemGitConfig) {
		FileBasedConfig old = this.systemGitConfig;
		this.systemGitConfig = systemGitConfig;
		return old;
	}

	/**
	 * Constructor for <code>MockSystemReader</code>
	 */
	public MockSystemReader() {
		init(Constants.OS_USER_NAME_KEY);
		init(Constants.GIT_AUTHOR_NAME_KEY);
		init(Constants.GIT_AUTHOR_EMAIL_KEY);
		init(Constants.GIT_COMMITTER_NAME_KEY);
		init(Constants.GIT_COMMITTER_EMAIL_KEY);
		setProperty(Constants.OS_USER_DIR, ".");
		userGitConfig = new MockConfig(null, null);
		jgitConfig = new MockConfig(null, null);
		systemGitConfig = new MockConfig(null, null);
		setCurrentPlatform();
	}

	private void init(String n) {
		setProperty(n, n);
	}

	/**
	 * Clear properties
	 */
	public void clearProperties() {
		values.clear();
	}

	/**
	 * Set a property
	 *
	 * @param key
	 *            the key
	 * @param value
	 *            the value
	 */
	public void setProperty(String key, String value) {
		values.put(key, value);
	}

	@Override
	public String getenv(String variable) {
		return values.get(variable);
	}

	@Override
	public String getProperty(String key) {
		return values.get(key);
	}

	@Override
	public FileBasedConfig openUserConfig(Config parent, FS fs) {
		assert parent == null || parent == systemGitConfig;
		return userGitConfig;
	}

	@Override
	public FileBasedConfig openSystemConfig(Config parent, FS fs) {
		assert parent == null;
		return systemGitConfig;
	}

	@Override
	public StoredConfig getUserConfig()
			throws IOException, ConfigInvalidException {
		return userGitConfig;
	}

	@Override
	public FileBasedConfig getJGitConfig() {
		return jgitConfig;
	}

	@Override
	public StoredConfig getSystemConfig()
			throws IOException, ConfigInvalidException {
		return systemGitConfig;
	}

	@Override
	public String getHostname() {
		return "fake.host.example.com";
	}

	@Override
	public long getCurrentTime() {
		return now;
	}

	@Override
	public MonotonicClock getClock() {
		return () -> {
			long t = getCurrentTime();
			return new ProposedTimestamp() {

				@Override
				public long read(TimeUnit unit) {
					return unit.convert(t, TimeUnit.MILLISECONDS);
				}

				@Override
				public void blockUntil(Duration maxWait) {
					// Do not wait.
				}
			};
		};
	}

	/**
	 * Adjusts the current time in seconds.
	 *
	 * @param secDelta
	 *            number of seconds to add to the current time.
	 * @since 4.2
	 */
	public void tick(int secDelta) {
		now += secDelta * 1000L;
	}

	@Override
	public int getTimezone(long when) {
		return getTimeZone().getOffset(when) / (60 * 1000);
	}

	@Override
	public TimeZone getTimeZone() {
		return TimeZone.getTimeZone("GMT-03:30");
	}

	@Override
	public Locale getLocale() {
		return Locale.US;
	}

	@Override
	public SimpleDateFormat getSimpleDateFormat(String pattern) {
		return new SimpleDateFormat(pattern, getLocale());
	}

	@Override
	public DateFormat getDateTimeInstance(int dateStyle, int timeStyle) {
		return DateFormat
				.getDateTimeInstance(dateStyle, timeStyle, getLocale());
	}

	/**
	 * Assign some properties for the currently executing platform
	 */
	public void setCurrentPlatform() {
		resetOsNames();
		setProperty("os.name", System.getProperty("os.name"));
		setProperty("file.separator", System.getProperty("file.separator"));
		setProperty("path.separator", System.getProperty("path.separator"));
		setProperty("line.separator", System.getProperty("line.separator"));
	}

	/**
	 * Emulate Windows
	 */
	public void setWindows() {
		resetOsNames();
		setProperty("os.name", "Windows");
		setProperty("file.separator", "\\");
		setProperty("path.separator", ";");
		setProperty("line.separator", "\r\n");
		setPlatformChecker();
	}

	/**
	 * Emulate Unix
	 */
	public void setUnix() {
		resetOsNames();
		setProperty("os.name", "*nix"); // Essentially anything but Windows
		setProperty("file.separator", "/");
		setProperty("path.separator", ":");
		setProperty("line.separator", "\n");
		setPlatformChecker();
	}

	private void resetOsNames() {
		Field field;
		try {
			field = SystemReader.class.getDeclaredField("isWindows");
			field.setAccessible(true);
			field.set(null, null);
			field = SystemReader.class.getDeclaredField("isMacOS");
			field.setAccessible(true);
			field.set(null, null);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	@Override
	public String toString() {
		return "MockSystemReader";
	}

	@Override
	public FileBasedConfig openJGitConfig(Config parent, FS fs) {
		return jgitConfig;
	}

}
