/*
 * Copyright (C) 2010, Google Inc.
 * 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.iplog;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileBasedConfig;
import org.eclipse.jgit.lib.LockFile;
import org.eclipse.jgit.lib.ObjectId;

/**
 * Manages the {@code .eclipse_iplog} file in a project.
 */
public class IpLogMeta {
	/** Default name of the {@code .eclipse_iplog} file. */
	public static final String IPLOG_CONFIG_FILE = ".eclipse_iplog";

	private static final String S_PROJECT = "project";

	private static final String S_CQ = "CQ";

	private static final String K_NAME = "name";

	private static final String K_COMMENTS = "comments";

	private static final String K_SKIP_COMMIT = "skipCommit";

	private static final String K_LICENSE = "license";

	private static final String K_DESCRIPTION = "description";

	private static final String K_USE = "use";

	private static final String K_STATE = "state";

	private List<Project> projects = new ArrayList<Project>();

	private Set<CQ> cqs = new HashSet<CQ>();

	List<Project> getProjects() {
		return projects;
	}

	Set<CQ> getCQs() {
		return cqs;
	}

	void loadFrom(Config cfg) {
		projects.clear();
		cqs.clear();

		for (String id : cfg.getSubsections(S_PROJECT)) {
			String name = cfg.getString(S_PROJECT, id, K_NAME);
			Project project = new Project(id, name);
			project.setComments(cfg.getString(S_PROJECT, id, K_COMMENTS));

			for (String c : cfg.getStringList(S_PROJECT, id, K_SKIP_COMMIT))
				project.addSkipCommit(ObjectId.fromString(c));
			for (String license : cfg.getStringList(S_PROJECT, id, K_LICENSE))
				project.addLicense(license);
			projects.add(project);
		}

		for (String id : cfg.getSubsections(S_CQ)) {
			CQ cq = new CQ(Long.parseLong(id));
			cq.setDescription(cfg.getString(S_CQ, id, K_DESCRIPTION));
			cq.setLicense(cfg.getString(S_CQ, id, K_LICENSE));
			cq.setUse(cfg.getString(S_CQ, id, K_USE));
			cq.setState(cfg.getString(S_CQ, id, K_STATE));
			cq.setComments(cfg.getString(S_CQ, id, K_COMMENTS));
			cqs.add(cq);
		}
	}

	/**
	 * Query the Eclipse Foundation's IPzilla database for CQ records.
	 * <p>
	 * Updates the local {@code .eclipse_iplog} configuration file with current
	 * information by deleting CQs which are no longer relevant, and adding or
	 * updating any CQs which currently exist in the database.
	 *
	 * @param file
	 *            local file to update with current CQ records.
	 * @param base
	 *            base https:// URL of the IPzilla server.
	 * @param username
	 *            username to login to IPzilla as. Must be a Bugzilla username
	 *            of someone authorized to query the project's IPzilla records.
	 * @param password
	 *            password for {@code username}.
	 * @throws IOException
	 *             IPzilla cannot be queried, or the local file cannot be read
	 *             from or written to.
	 * @throws ConfigInvalidException
	 *             the local file cannot be read, as it is not a valid
	 *             configuration file format.
	 */
	public void syncCQs(File file, URL base, String username, String password)
			throws IOException, ConfigInvalidException {
		if (!file.getParentFile().exists())
			file.getParentFile().mkdirs();

		LockFile lf = new LockFile(file);
		if (!lf.lock())
			throw new IOException("Cannot lock " + file);
		try {
			FileBasedConfig cfg = new FileBasedConfig(file);
			cfg.load();
			loadFrom(cfg);

			IPZillaQuery ipzilla = new IPZillaQuery(base, username, password);
			Set<CQ> current = ipzilla.getCQs(projects);

			for (CQ cq : sort(current, CQ.COMPARATOR)) {
				String id = Long.toString(cq.getID());

				set(cfg, S_CQ, id, K_DESCRIPTION, cq.getDescription());
				set(cfg, S_CQ, id, K_LICENSE, cq.getLicense());
				set(cfg, S_CQ, id, K_USE, cq.getUse());
				set(cfg, S_CQ, id, K_STATE, cq.getState());
				set(cfg, S_CQ, id, K_COMMENTS, cq.getComments());
			}

			for (CQ cq : cqs) {
				if (!current.contains(cq))
					cfg.unsetSection(S_CQ, Long.toString(cq.getID()));
			}

			lf.write(Constants.encode(cfg.toText()));
			if (!lf.commit())
				throw new IOException("Cannot write " + file);
		} finally {
			lf.unlock();
		}
	}

	private static void set(Config cfg, String section, String subsection,
			String key, String value) {
		if (value == null || "".equals(value))
			cfg.unset(section, subsection, key);
		else
			cfg.setString(section, subsection, key, value);
	}

	private static <T, Q extends Comparator<T>> Iterable<T> sort(
			Collection<T> objs, Q cmp) {
		ArrayList<T> sorted = new ArrayList<T>(objs);
		Collections.sort(sorted, cmp);
		return sorted;
	}
}
