/*
 * This file is part of the DistSim distributed simulation framework (client)
 * Copyright (C) 2007 Ulf Hermann
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */
package brn.distsim.client.data;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

public class Package implements Saveable {

	private Connection definitions;

	private String name;

	private String version;

	private String architecture;

	private String url;

	public Package(Connection definitions, String name, String version,
			String architecture, String url) {
		this.definitions = definitions;
		this.name = name;
		this.version = version;
		this.architecture = architecture;
		this.url = url;
	}

	public void performDbInsert(int x) throws SQLException {
		performDbInsert();
	}

	public void performDbInsert() throws SQLException {
		definitions.createStatement().executeUpdate(
				"INSERT INTO packages VALUES ('" + name + "', '" + version
						+ "', '" + architecture + "', '" + url + "');");
	}

	public void upload(String localFile) throws IOException {
		InputStream in = new FileInputStream(localFile);
		URLConnection outUrl = new URL(url).openConnection();
		outUrl.setDoOutput(true);
		outUrl.connect();
		OutputStream out = outUrl.getOutputStream();
		int read = 0;
		byte[] data = new byte[1024];
		while ((read = in.read(data)) > 0)
			out.write(data, 0, read);
    out.flush();
    out.close();
	}

	/**
	 * return a map of all package names and versions, disregarding the
	 * architectures
	 *
	 * @param db
	 *            the database to be queried
	 * @return a map of package names to lists of versions for these packages
	 * @throws SQLException
	 *             id the query fails
	 */
	public static Map<String, List<String>> getAllVersions(Connection db)
			throws SQLException {
		ResultSet versions = db.createStatement().executeQuery(
				"SELECT name, version FROM packages ORDER BY name, version;");
		Map<String, List<String>> ret = new HashMap<String, List<String>>();
		String prevName = null;
		List<String> currentVersions = null;
		while (versions.next()) {
			String name = versions.getString(1);
			if (!name.equals(prevName)) {
				prevName = name;
				currentVersions = new LinkedList<String>();
				ret.put(name, currentVersions);
			}
			currentVersions.add(versions.getString(2));
		}
		return ret;
	}

	public static List<String> getNames(Connection db) throws SQLException {
		ResultSet names = db.createStatement().executeQuery(
				"SELECT DISTINCT name FROM packages ORDER BY name;");
		return DbBackedEntries.namesToList(names);
	}

	public static List<String> getVersions(Connection db, String name)
			throws SQLException {
		ResultSet versions = db.createStatement().executeQuery(
				"SELECT DISTINCT version FROM packages WHERE name ='" + name
						+ "' ORDER BY version;");
		return DbBackedEntries.namesToList(versions);
	}

	public static List<String> getArchitectures(Connection db, String name,
			String version) throws SQLException {
		ResultSet architectures = db.createStatement().executeQuery(
				"SELECT architecture FROM packages WHERE name ='" + name
						+ "' AND version='" + version
						+ "' ORDER BY architecture;");
		return DbBackedEntries.namesToList(architectures);
	}

	public void performDbUpdate() throws SQLException {
		definitions.createStatement().executeUpdate(
				"REPLACE INTO packages VALUES ('" + name + "', '" + version
						+ "', '" + architecture + "', '" + url + "');");
	}

	public void performDbDelete() throws SQLException {
		definitions.createStatement().executeUpdate(
				"DELETE FROM packages WHERE name='" + name + "' AND version='"
						+ version + "' AND architecture='" + architecture
						+ "');");
	}

	public String getName() {
		return name;
	}

}
