/*
 * Copyright 2011 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.client;

import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.net.ConnectException;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.KeyStroke;
import javax.swing.SwingWorker;
import javax.swing.UIManager;

import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.util.FS;

import com.gitblit.Constants;
import com.gitblit.GitBlitException.ForbiddenException;
import com.gitblit.models.FeedModel;
import com.gitblit.utils.Base64;
import com.gitblit.utils.StringUtils;

/**
 * Gitblit Manager issues JSON RPC requests to a Gitblit server.
 *
 * @author James Moger
 *
 */
public class GitblitManager extends JFrame implements RegistrationsDialog.RegistrationListener {

	private static final long serialVersionUID = 1L;
	private static final String SERVER = "server";
	private static final String FEED = "feed";
	private final SimpleDateFormat dateFormat;
	private JTabbedPane serverTabs;
	private File configFile = new File(System.getProperty("user.home"), ".gitblit/config");

	private Map<String, GitblitRegistration> registrations = new LinkedHashMap<String, GitblitRegistration>();
	private JMenu recentMenu;
	private int maxRecentCount = 5;

	private GitblitManager() {
		super();
		dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
		dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
	}

	private void initialize() {
		setContentPane(getCenterPanel());
		setIconImage(new ImageIcon(getClass().getResource("/gitblt-favicon.png")).getImage());
		setTitle("Gitblit Manager v" + Constants.getVersion() + " (" + Constants.getBuildDate() + ")");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent event) {
				saveSizeAndPosition();
			}

			@Override
			public void windowOpened(WindowEvent event) {
				manageRegistrations();
			}
		});

		setSizeAndPosition();
		loadRegistrations();
		rebuildRecentMenu();
	}

	private void setSizeAndPosition() {
		String sz = null;
		String pos = null;
		try {
			StoredConfig config = getConfig();
			sz = config.getString("ui", null, "size");
			pos = config.getString("ui", null, "position");
		} catch (Throwable t) {
			t.printStackTrace();
		}

		// try to restore saved window size
		if (StringUtils.isEmpty(sz)) {
			setSize(850, 500);
		} else {
			String[] chunks = sz.split("x");
			int width = Integer.parseInt(chunks[0]);
			int height = Integer.parseInt(chunks[1]);
			setSize(width, height);
		}

		// try to restore saved window position
		if (StringUtils.isEmpty(pos)) {
			setLocationRelativeTo(null);
		} else {
			String[] chunks = pos.split(",");
			int x = Integer.parseInt(chunks[0]);
			int y = Integer.parseInt(chunks[1]);
			setLocation(x, y);
		}
	}

	private void saveSizeAndPosition() {
		try {
			// save window size and position
			StoredConfig config = getConfig();
			Dimension sz = GitblitManager.this.getSize();
			config.setString("ui", null, "size",
					MessageFormat.format("{0,number,0}x{1,number,0}", sz.width, sz.height));
			Point pos = GitblitManager.this.getLocationOnScreen();
			config.setString("ui", null, "position",
					MessageFormat.format("{0,number,0},{1,number,0}", pos.x, pos.y));
			config.save();
		} catch (Throwable t) {
			Utils.showException(GitblitManager.this, t);
		}
	}

	private JMenuBar setupMenu() {
		JMenuBar menuBar = new JMenuBar();
		JMenu serversMenu = new JMenu(Translation.get("gb.servers"));
		menuBar.add(serversMenu);
		recentMenu = new JMenu(Translation.get("gb.recent"));
		serversMenu.add(recentMenu);

		JMenuItem manage = new JMenuItem(Translation.get("gb.manage") + "...");
		manage.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_M, KeyEvent.CTRL_DOWN_MASK, false));
		manage.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent event) {
				manageRegistrations();
			}
		});
		serversMenu.add(manage);

		return menuBar;
	}

	private JPanel getCenterPanel() {
		serverTabs = new JTabbedPane(JTabbedPane.TOP);
		JMenuBar menubar = setupMenu();
		JPanel panel = new JPanel(new BorderLayout());
		panel.add(menubar, BorderLayout.NORTH);
		panel.add(serverTabs, BorderLayout.CENTER);
		return panel;
	}

	private void manageRegistrations() {
		RegistrationsDialog dialog = new RegistrationsDialog(new ArrayList<GitblitRegistration>(
				registrations.values()), this);
		dialog.setLocationRelativeTo(GitblitManager.this);
		dialog.setVisible(true);
	}

	@Override
	public void login(GitblitRegistration reg) {
		if (!reg.savePassword && (reg.password == null || reg.password.length == 0)) {
			// prompt for password
			EditRegistrationDialog dialog = new EditRegistrationDialog(this, reg, true);
			dialog.setLocationRelativeTo(GitblitManager.this);
			dialog.setVisible(true);
			GitblitRegistration newReg = dialog.getRegistration();
			if (newReg == null) {
				// user canceled
				return;
			}
			// preserve feeds
			newReg.feeds.addAll(reg.feeds);

			// use new reg
			reg = newReg;
		}

		// login
		setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
		final GitblitRegistration registration = reg;
		final GitblitPanel panel = new GitblitPanel(registration, this);
		SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>() {

			@Override
			protected Boolean doInBackground() throws IOException {
				panel.login();
				return true;
			}

			@Override
			protected void done() {
				try {
					boolean success = get();
					serverTabs.addTab(registration.name, panel);
					int idx = serverTabs.getTabCount() - 1;
					serverTabs.setSelectedIndex(idx);
					serverTabs.setTabComponentAt(idx, new ClosableTabComponent(registration.name,
							null, serverTabs, panel));
					registration.lastLogin = new Date();
					saveRegistration(registration.name, registration);
					registrations.put(registration.name, registration);
					rebuildRecentMenu();
					if (!registration.savePassword) {
						// clear password
						registration.password = null;
					}
				} catch (Throwable t) {
					Throwable cause = t.getCause();
					if (cause instanceof ConnectException) {
						JOptionPane.showMessageDialog(GitblitManager.this, cause.getMessage(),
								Translation.get("gb.error"), JOptionPane.ERROR_MESSAGE);
					} else if (cause instanceof ForbiddenException) {
						JOptionPane
								.showMessageDialog(
										GitblitManager.this,
										"This Gitblit server does not allow RPC Management or Administration",
										Translation.get("gb.error"), JOptionPane.ERROR_MESSAGE);
					} else {
						Utils.showException(GitblitManager.this, t);
					}
				} finally {
					setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
				}
			}
		};
		worker.execute();
	}

	private void rebuildRecentMenu() {
		recentMenu.removeAll();
		ImageIcon icon = new ImageIcon(getClass().getResource("/gitblt-favicon.png"));
		List<GitblitRegistration> list = new ArrayList<GitblitRegistration>(registrations.values());
		Collections.sort(list, new Comparator<GitblitRegistration>() {
			@Override
			public int compare(GitblitRegistration o1, GitblitRegistration o2) {
				return o2.lastLogin.compareTo(o1.lastLogin);
			}
		});
		if (list.size() > maxRecentCount) {
			list = list.subList(0, maxRecentCount);
		}
		for (int i = 0; i < list.size(); i++) {
			final GitblitRegistration reg = list.get(i);
			JMenuItem item = new JMenuItem(reg.name, icon);
			item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_1 + i, KeyEvent.CTRL_DOWN_MASK,
					false));
			item.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					login(reg);
				}
			});
			recentMenu.add(item);
		}
	}

	private void loadRegistrations() {
		try {
			StoredConfig config = getConfig();
			Set<String> servers = config.getSubsections(SERVER);
			for (String server : servers) {
				Date lastLogin = new Date(0);
				String date = config.getString(SERVER, server, "lastLogin");
				if (!StringUtils.isEmpty(date)) {
					lastLogin = dateFormat.parse(date);
				}
				String url = config.getString(SERVER, server, "url");
				String account = config.getString(SERVER, server, "account");
				char[] password;
				String pw = config.getString(SERVER, server, "password");
				if (StringUtils.isEmpty(pw)) {
					password = new char[0];
				} else {
					password = new String(Base64.decode(pw)).toCharArray();
				}
				GitblitRegistration reg = new GitblitRegistration(server, url, account, password) {
					private static final long serialVersionUID = 1L;

					@Override
					protected void cacheFeeds() {
						writeFeedCache(this);
					}
				};
				String[] feeds = config.getStringList(SERVER, server, FEED);
				if (feeds != null) {
					// deserialize the field definitions
					for (String definition : feeds) {
						FeedModel feed = new FeedModel(definition);
						reg.feeds.add(feed);
					}
				}
				reg.lastLogin = lastLogin;
				loadFeedCache(reg);
				registrations.put(reg.name, reg);
			}
		} catch (Throwable t) {
			Utils.showException(GitblitManager.this, t);
		}
	}

	@Override
	public boolean saveRegistration(String name, GitblitRegistration reg) {
		try {
			StoredConfig config = getConfig();
			if (!StringUtils.isEmpty(name) && !name.equals(reg.name)) {
				// delete old registration
				registrations.remove(name);
				config.unsetSection(SERVER, name);
			}

			// update registration
			config.setString(SERVER, reg.name, "url", reg.url);
			config.setString(SERVER, reg.name, "account", reg.account);
			if (reg.savePassword) {
				config.setString(SERVER, reg.name, "password",
						Base64.encodeBytes(new String(reg.password).getBytes("UTF-8")));
			} else {
				config.setString(SERVER, reg.name, "password", "");
			}
			if (reg.lastLogin != null) {
				config.setString(SERVER, reg.name, "lastLogin", dateFormat.format(reg.lastLogin));
			}
			// serialize the feed definitions
			List<String> definitions = new ArrayList<String>();
			for (FeedModel feed : reg.feeds) {
				definitions.add(feed.toString());
			}
			if (definitions.size() > 0) {
				config.setStringList(SERVER, reg.name, FEED, definitions);
			}
			config.save();
			return true;
		} catch (Throwable t) {
			Utils.showException(GitblitManager.this, t);
		}
		return false;
	}

	@Override
	public boolean deleteRegistrations(List<GitblitRegistration> list) {
		boolean success = false;
		try {
			StoredConfig config = getConfig();
			for (GitblitRegistration reg : list) {
				config.unsetSection(SERVER, reg.name);
				registrations.remove(reg.name);
			}
			config.save();
			success = true;
		} catch (Throwable t) {
			Utils.showException(GitblitManager.this, t);
		}
		return success;
	}

	private StoredConfig getConfig() throws IOException, ConfigInvalidException {
		FileBasedConfig config = new FileBasedConfig(configFile, FS.detect());
		config.load();
		return config;
	}

	private void loadFeedCache(GitblitRegistration reg) {
		File feedCache = new File(configFile.getParentFile(), StringUtils.getSHA1(reg.toString())
				+ ".cache");
		if (!feedCache.exists()) {
			// no cache for this registration
			return;
		}
		try {
			BufferedReader reader = new BufferedReader(new FileReader(feedCache));
			Map<String, Date> cache = new HashMap<String, Date>();
			SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
			String line = null;
			while ((line = reader.readLine()) != null) {
				String[] kvp = line.split("=");
				cache.put(kvp[0], df.parse(kvp[1]));
			}
			reader.close();
			for (FeedModel feed : reg.feeds) {
				String name = feed.toString();
				if (cache.containsKey(name)) {
					feed.currentRefreshDate = cache.get(name);
				}
			}
		} catch (Exception e) {
			Utils.showException(GitblitManager.this, e);
		}
	}

	private void writeFeedCache(GitblitRegistration reg) {
		try {
			File feedCache = new File(configFile.getParentFile(), StringUtils.getSHA1(reg
					.toString()) + ".cache");
			FileWriter writer = new FileWriter(feedCache);
			for (FeedModel feed : reg.feeds) {
				writer.append(MessageFormat.format("{0}={1,date,yyyy-MM-dd'T'HH:mm:ss}\n",
						feed.toString(), feed.currentRefreshDate));
			}
			writer.close();
		} catch (Exception e) {
			Utils.showException(GitblitManager.this, e);
		}
	}

	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			@Override
			public void run() {
				try {
					UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
				} catch (Exception e) {
				}
				GitblitManager frame = new GitblitManager();
				frame.initialize();
				frame.setVisible(true);
			}
		});
	}
}
