/*
 * Copyright 2014 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.transport.ssh;

import java.io.File;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import com.gitblit.Constants.AccessPermission;
import com.gitblit.Keys;
import com.gitblit.manager.IRuntimeManager;
import com.google.common.base.Charsets;
import com.google.common.base.Joiner;
import com.google.common.io.Files;

/**
 * Manages public keys on the filesystem.
 *
 * @author James Moger
 *
 */
public class FileKeyManager extends IPublicKeyManager {

	protected final IRuntimeManager runtimeManager;

	protected final Map<File, Long> lastModifieds;

	public FileKeyManager(IRuntimeManager runtimeManager) {
		this.runtimeManager = runtimeManager;
		this.lastModifieds = new ConcurrentHashMap<File, Long>();
	}

	@Override
	public String toString() {
		File dir = runtimeManager.getFileOrFolder(Keys.git.sshKeysFolder, "${baseFolder}/ssh");
		return MessageFormat.format("{0} ({1})", getClass().getSimpleName(), dir);
	}

	@Override
	public FileKeyManager start() {
		log.info(toString());
		return this;
	}

	@Override
	public boolean isReady() {
		return true;
	}

	@Override
	public FileKeyManager stop() {
		return this;
	}

	@Override
	protected boolean isStale(String username) {
		File keystore = getKeystore(username);
		if (!keystore.exists()) {
			// keystore may have been deleted
			return true;
		}

		if (lastModifieds.containsKey(keystore)) {
			// compare modification times
			long lastModified = lastModifieds.get(keystore);
			return lastModified != keystore.lastModified();
		}

		// assume stale
		return true;
	}

	@Override
	protected List<SshKey> getKeysImpl(String username) {
		try {
			log.info("loading ssh keystore for {}", username);
			File keystore = getKeystore(username);
			if (!keystore.exists()) {
				return null;
			}
			if (keystore.exists()) {
				List<SshKey> list = new ArrayList<SshKey>();
				for (String entry : Files.readLines(keystore, Charsets.ISO_8859_1)) {
					if (entry.trim().length() == 0) {
						// skip blanks
						continue;
					}
					if (entry.charAt(0) == '#') {
						// skip comments
						continue;
					}
					String [] parts = entry.split(" ", 2);
					AccessPermission perm = AccessPermission.fromCode(parts[0]);
					if (perm.equals(AccessPermission.NONE)) {
						// ssh-rsa DATA COMMENT
						SshKey key = new SshKey(entry);
						list.add(key);
					} else if (perm.exceeds(AccessPermission.NONE)) {
						// PERMISSION ssh-rsa DATA COMMENT
						SshKey key = new SshKey(parts[1]);
						key.setPermission(perm);
						list.add(key);
					}
				}

				if (list.isEmpty()) {
					return null;
				}

				lastModifieds.put(keystore, keystore.lastModified());
				return list;
			}
		} catch (IOException e) {
			throw new RuntimeException("Cannot read ssh keys", e);
		}
		return null;
	}

	/**
	 * Adds a unique key to the keystore.  This function determines uniqueness
	 * by disregarding the comment/description field during key comparisons.
	 */
	@Override
	public boolean addKey(String username, SshKey key) {
		try {
			boolean replaced = false;
			List<String> lines = new ArrayList<String>();
			File keystore = getKeystore(username);
			if (keystore.exists()) {
				for (String entry : Files.readLines(keystore, Charsets.ISO_8859_1)) {
					String line = entry.trim();
					if (line.length() == 0) {
						// keep blanks
						lines.add(entry);
						continue;
					}
					if (line.charAt(0) == '#') {
						// keep comments
						lines.add(entry);
						continue;
					}

					SshKey oldKey = parseKey(line);
					if (key.equals(oldKey)) {
						// replace key
						lines.add(key.getPermission() + " " + key.getRawData());
						replaced = true;
					} else {
						// retain key
						lines.add(entry);
					}
				}
			}

			if (!replaced) {
				// new key, append
				lines.add(key.getPermission() + " " + key.getRawData());
			}

			// write keystore
			String content = Joiner.on("\n").join(lines).trim().concat("\n");
			Files.write(content, keystore, Charsets.ISO_8859_1);

			lastModifieds.remove(keystore);
			keyCache.invalidate(username);
			return true;
		} catch (IOException e) {
			throw new RuntimeException("Cannot add ssh key", e);
		}
	}

	/**
	 * Removes the specified key from the keystore.
	 */
	@Override
	public boolean removeKey(String username, SshKey key) {
		try {
			File keystore = getKeystore(username);
			if (keystore.exists()) {
				List<String> lines = new ArrayList<String>();
				for (String entry : Files.readLines(keystore, Charsets.ISO_8859_1)) {
					String line = entry.trim();
					if (line.length() == 0) {
						// keep blanks
						lines.add(entry);
						continue;
					}
					if (line.charAt(0) == '#') {
						// keep comments
						lines.add(entry);
						continue;
					}

					// only include keys that are NOT rmKey
					SshKey oldKey = parseKey(line);
					if (!key.equals(oldKey)) {
						lines.add(entry);
					}
				}
				if (lines.isEmpty()) {
					keystore.delete();
				} else {
					// write keystore
					String content = Joiner.on("\n").join(lines).trim().concat("\n");
					Files.write(content, keystore, Charsets.ISO_8859_1);
				}

				lastModifieds.remove(keystore);
				keyCache.invalidate(username);
				return true;
			}
		} catch (IOException e) {
			throw new RuntimeException("Cannot remove ssh key", e);
		}
		return false;
	}

	@Override
	public boolean removeAllKeys(String username) {
		File keystore = getKeystore(username);
		if (keystore.delete()) {
			lastModifieds.remove(keystore);
			keyCache.invalidate(username);
			return true;
		}
		return false;
	}

	protected File getKeystore(String username) {
		File dir = runtimeManager.getFileOrFolder(Keys.git.sshKeysFolder, "${baseFolder}/ssh");
		dir.mkdirs();
		File keys = new File(dir, username + ".keys");
		return keys;
	}

	protected SshKey parseKey(String line) {
		String [] parts = line.split(" ", 2);
		AccessPermission perm = AccessPermission.fromCode(parts[0]);
		if (perm.equals(AccessPermission.NONE)) {
			// ssh-rsa DATA COMMENT
			SshKey key = new SshKey(line);
			return key;
		} else {
			// PERMISSION ssh-rsa DATA COMMENT
			SshKey key = new SshKey(parts[1]);
			key.setPermission(perm);
			return key;
		}
	}
}
