/*
 * Copyright (C) 2012, Tomasz Zarna <Tomasz.Zarna@pl.ibm.com> and
 * other copyright owners as documented in the project's IP log.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Distribution License v1.0 which accompanies this
 * distribution, is reproduced below, and is available at
 * http://www.eclipse.org/org/documents/edl-v10.php
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * - Neither the name of the Eclipse Foundation, Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
package org.eclipse.jgit.pgm;

import java.io.File;
import java.io.IOException;
import java.util.Set;

import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.NotSupportedException;
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.StringUtils;
import org.eclipse.jgit.util.SystemReader;
import org.kohsuke.args4j.Option;

@Command(common = true, usage = "usage_getAndSetOptions")
class Config extends TextBuiltin {
	@Option(name = "--system", usage = "usage_configSystem")
	private boolean system;

	@Option(name = "--global", usage = "usage_configGlobal")
	private boolean global;

	@Option(name = "--local", usage = "usage_configLocal")
	private boolean local;

	@Option(name = "--list", aliases = { "-l" }, usage = "usage_configList")
	private boolean list;

	@Option(name = "--file", aliases = { "-f" }, metaVar = "metaVar_file", usage = "usage_configFile")
	private File configFile;

	/** {@inheritDoc} */
	@Override
	protected void run() throws Exception {
		if (list)
			list();
		else
			throw new NotSupportedException(
					"only --list option is currently supported"); //$NON-NLS-1$
	}

	private void list() throws IOException, ConfigInvalidException {
		final FS fs = getRepository().getFS();
		if (configFile != null) {
			list(new FileBasedConfig(configFile, fs));
			return;
		}
		if (system
				|| (isListAll() && StringUtils.isEmptyOrNull(SystemReader
						.getInstance()
						.getenv(Constants.GIT_CONFIG_NOSYSTEM_KEY))))
			list(SystemReader.getInstance().openSystemConfig(null, fs));
		if (global || isListAll())
			list(SystemReader.getInstance().openUserConfig(null, fs));
		if (local || isListAll())
			list(new FileBasedConfig(fs.resolve(getRepository().getDirectory(),
					Constants.CONFIG), fs));
	}

	private boolean isListAll() {
		return !system && !global && !local && configFile == null;
	}

	private void list(StoredConfig config) throws IOException,
			ConfigInvalidException {
		config.load();
		Set<String> sections = config.getSections();
		for (String section : sections) {
			Set<String> names = config.getNames(section);
			for (String name : names) {
				for (String value : config.getStringList(section, null, name))
					outw.println(section + "." + name + "=" + value); //$NON-NLS-1$ //$NON-NLS-2$
			}
			if (names.isEmpty()) {
				for (String subsection : config.getSubsections(section)) {
					names = config.getNames(section, subsection);
					for (String name : names) {
						for (String value : config.getStringList(section,
								subsection, name))
							outw.println(section + "." + subsection + "." //$NON-NLS-1$ //$NON-NLS-2$
									+ name + "=" + value); //$NON-NLS-1$
					}
				}
			}
		}
	}
}
