/*
 * 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.FlowLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.List;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.JRootPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.KeyStroke;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

/**
 * Displays a list of registrations and allows management of server
 * registrations.
 *
 * @author James Moger
 *
 */
public class RegistrationsDialog extends JDialog {

	interface RegistrationListener {

		void login(GitblitRegistration reg);

		boolean saveRegistration(String name, GitblitRegistration reg);

		boolean deleteRegistrations(List<GitblitRegistration> list);
	}

	private static final long serialVersionUID = 1L;

	private final List<GitblitRegistration> registrations;

	private final RegistrationListener listener;

	private JTable registrationsTable;

	private RegistrationsTableModel model;

	public RegistrationsDialog(List<GitblitRegistration> registrations,
			RegistrationListener listener) {
		super();
		this.registrations = registrations;
		this.listener = listener;
		setTitle(Translation.get("gb.manage"));
		setIconImage(new ImageIcon(getClass().getResource("/gitblt-favicon.png")).getImage());
		initialize();
		setSize(600, 400);
	}

	@Override
	protected JRootPane createRootPane() {
		KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0);
		JRootPane rootPane = new JRootPane();
		rootPane.registerKeyboardAction(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent actionEvent) {
				setVisible(false);
			}
		}, stroke, JComponent.WHEN_IN_FOCUSED_WINDOW);
		return rootPane;
	}

	private void initialize() {
		NameRenderer nameRenderer = new NameRenderer();
		model = new RegistrationsTableModel(registrations);
		registrationsTable = Utils.newTable(model, Utils.DATE_FORMAT);

		String id = registrationsTable
				.getColumnName(RegistrationsTableModel.Columns.Name.ordinal());
		registrationsTable.getColumn(id).setCellRenderer(nameRenderer);
		registrationsTable.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				if (e.getClickCount() == 2) {
					login();
				}
			}
		});

		final JButton create = new JButton(Translation.get("gb.create"));
		create.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent event) {
				create();
			}
		});

		final JButton login = new JButton(Translation.get("gb.login"));
		login.setEnabled(false);
		login.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent event) {
				login();
			}
		});

		final JButton edit = new JButton(Translation.get("gb.edit"));
		edit.setEnabled(false);
		edit.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent event) {
				edit();
			}
		});

		final JButton delete = new JButton(Translation.get("gb.delete"));
		delete.setEnabled(false);
		delete.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent event) {
				delete();
			}
		});

		registrationsTable.getSelectionModel().addListSelectionListener(
				new ListSelectionListener() {
					@Override
					public void valueChanged(ListSelectionEvent e) {
						if (e.getValueIsAdjusting()) {
							return;
						}
						boolean singleSelection = registrationsTable.getSelectedRowCount() == 1;
						boolean selected = registrationsTable.getSelectedRow() > -1;
						login.setEnabled(singleSelection);
						edit.setEnabled(singleSelection);
						delete.setEnabled(selected);
					}
				});

		JPanel controls = new JPanel(new FlowLayout(FlowLayout.CENTER, 5, 0));
		controls.add(create);
		controls.add(login);
		controls.add(edit);
		controls.add(delete);

		final Insets insets = new Insets(5, 5, 5, 5);
		JPanel centerPanel = new JPanel(new BorderLayout(5, 5)) {

			private static final long serialVersionUID = 1L;

			@Override
			public Insets getInsets() {
				return insets;
			}
		};
		centerPanel.add(new HeaderPanel(Translation.get("gb.servers"), null), BorderLayout.NORTH);
		centerPanel.add(new JScrollPane(registrationsTable), BorderLayout.CENTER);
		centerPanel.add(controls, BorderLayout.SOUTH);

		getContentPane().setLayout(new BorderLayout(5, 5));
		getContentPane().add(centerPanel, BorderLayout.CENTER);
	}

	private void login() {
		int viewRow = registrationsTable.getSelectedRow();
		int modelRow = registrationsTable.convertRowIndexToModel(viewRow);
		GitblitRegistration reg = registrations.get(modelRow);
		RegistrationsDialog.this.setVisible(false);
		listener.login(reg);
	}

	private void create() {
		EditRegistrationDialog dialog = new EditRegistrationDialog(getOwner());
		dialog.setLocationRelativeTo(this);
		dialog.setVisible(true);
		GitblitRegistration reg = dialog.getRegistration();
		if (reg == null) {
			return;
		}
		if (listener.saveRegistration(reg.name, reg)) {
			model.list.add(reg);
			model.fireTableDataChanged();
		}
	}

	private void edit() {
		int viewRow = registrationsTable.getSelectedRow();
		int modelRow = registrationsTable.convertRowIndexToModel(viewRow);
		GitblitRegistration reg = registrations.get(modelRow);
		String originalName = reg.name;
		EditRegistrationDialog dialog = new EditRegistrationDialog(getOwner(), reg, false);
		dialog.setLocationRelativeTo(this);
		dialog.setVisible(true);
		reg = dialog.getRegistration();
		if (reg == null) {
			return;
		}
		if (listener.saveRegistration(originalName, reg)) {
			model.fireTableDataChanged();
		}
	}

	private void delete() {
		List<GitblitRegistration> list = new ArrayList<GitblitRegistration>();
		for (int i : registrationsTable.getSelectedRows()) {
			int model = registrationsTable.convertRowIndexToModel(i);
			GitblitRegistration reg = registrations.get(model);
			list.add(reg);
		}
		if (listener.deleteRegistrations(list)) {
			registrations.removeAll(list);
			model.fireTableDataChanged();
		}
	}
}
