/*
 * 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.Color;
import java.awt.FlowLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.RowFilter;
import javax.swing.SwingConstants;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableRowSorter;

import com.gitblit.Constants;
import com.gitblit.Constants.RpcRequest;
import com.gitblit.Keys;
import com.gitblit.models.FeedModel;
import com.gitblit.models.RegistrantAccessPermission;
import com.gitblit.models.RepositoryModel;
import com.gitblit.utils.StringUtils;

/**
 * RSS Feeds Panel displays recent entries and launches the browser to view the
 * commit. commitdiff, or tree of a commit.
 *
 * @author James Moger
 *
 */
public abstract class RepositoriesPanel extends JPanel {

	private static final long serialVersionUID = 1L;

	private final GitblitClient gitblit;

	private HeaderPanel header;

	private JTable table;

	private RepositoriesTableModel tableModel;

	private TableRowSorter<RepositoriesTableModel> defaultSorter;

	private JButton createRepository;

	private JButton editRepository;

	private JButton delRepository;

	private JTextField filterTextfield;

	private JButton clearCache;

	public RepositoriesPanel(GitblitClient gitblit) {
		super();
		this.gitblit = gitblit;
		initialize();
	}

	private void initialize() {
		final JButton browseRepository = new JButton(Translation.get("gb.browse"));
		browseRepository.setEnabled(false);
		browseRepository.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				RepositoryModel model = getSelectedRepositories().get(0);
				String url = gitblit.getURL("summary", model.name, null);
				Utils.browse(url);
			}
		});

		JButton refreshRepositories = new JButton(Translation.get("gb.refresh"));
		refreshRepositories.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				refreshRepositories();
			}
		});

		clearCache = new JButton(Translation.get("gb.clearCache"));
		clearCache.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				clearCache();
			}
		});

		createRepository = new JButton(Translation.get("gb.create"));
		createRepository.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				createRepository();
			}
		});

		editRepository = new JButton(Translation.get("gb.edit"));
		editRepository.setEnabled(false);
		editRepository.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				editRepository(getSelectedRepositories().get(0));
			}
		});

		delRepository = new JButton(Translation.get("gb.delete"));
		delRepository.setEnabled(false);
		delRepository.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				deleteRepositories(getSelectedRepositories());
			}
		});

		final JButton subscribeRepository = new JButton(Translation.get("gb.subscribe") + "...");
		subscribeRepository.setEnabled(false);
		subscribeRepository.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				List<FeedModel> feeds = gitblit.getAvailableFeeds(getSelectedRepositories().get(0));
				subscribeFeeds(feeds);
			}
		});

		final JButton logRepository = new JButton(Translation.get("gb.log") + "...");
		logRepository.setEnabled(false);
		logRepository.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				RepositoryModel model = getSelectedRepositories().get(0);
				showSearchDialog(false, model);
			}
		});

		final JButton searchRepository = new JButton(Translation.get("gb.search") + "...");
		searchRepository.setEnabled(false);
		searchRepository.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				RepositoryModel model = getSelectedRepositories().get(0);
				showSearchDialog(true, model);
			}
		});

		SubscribedRepositoryRenderer nameRenderer = new SubscribedRepositoryRenderer(gitblit);
		IndicatorsRenderer typeRenderer = new IndicatorsRenderer();

		DefaultTableCellRenderer sizeRenderer = new DefaultTableCellRenderer();
		sizeRenderer.setHorizontalAlignment(SwingConstants.RIGHT);
		sizeRenderer.setForeground(new Color(0, 0x80, 0));

		DefaultTableCellRenderer ownerRenderer = new DefaultTableCellRenderer();
		ownerRenderer.setForeground(Color.gray);
		ownerRenderer.setHorizontalAlignment(SwingConstants.CENTER);

		tableModel = new RepositoriesTableModel();
		defaultSorter = new TableRowSorter<RepositoriesTableModel>(tableModel);
		table = Utils.newTable(tableModel, Utils.DATE_FORMAT);
		table.setRowSorter(defaultSorter);
		table.getRowSorter().toggleSortOrder(RepositoriesTableModel.Columns.Name.ordinal());

		setRepositoryRenderer(RepositoriesTableModel.Columns.Name, nameRenderer, -1);
		setRepositoryRenderer(RepositoriesTableModel.Columns.Indicators, typeRenderer, 100);
		setRepositoryRenderer(RepositoriesTableModel.Columns.Owner, ownerRenderer, -1);
		setRepositoryRenderer(RepositoriesTableModel.Columns.Size, sizeRenderer, 60);

		table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
			@Override
			public void valueChanged(ListSelectionEvent e) {
				if (e.getValueIsAdjusting()) {
					return;
				}
				boolean singleSelection = table.getSelectedRowCount() == 1;
				boolean selected = table.getSelectedRow() > -1;
				if (singleSelection) {
					RepositoryModel repository = getSelectedRepositories().get(0);
					browseRepository.setEnabled(repository.hasCommits);
					logRepository.setEnabled(repository.hasCommits);
					searchRepository.setEnabled(repository.hasCommits);
					subscribeRepository.setEnabled(repository.hasCommits);
				} else {
					browseRepository.setEnabled(false);
					logRepository.setEnabled(false);
					searchRepository.setEnabled(false);
					subscribeRepository.setEnabled(false);
				}
				delRepository.setEnabled(selected);
				if (selected) {
					int viewRow = table.getSelectedRow();
					int modelRow = table.convertRowIndexToModel(viewRow);
					RepositoryModel model = ((RepositoriesTableModel) table.getModel()).list
							.get(modelRow);
					editRepository.setEnabled(singleSelection
							&& (gitblit.allowManagement() || gitblit.isOwner(model)));
				} else {
					editRepository.setEnabled(false);
				}
			}
		});

		table.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				if (e.getClickCount() == 2 && gitblit.allowManagement()) {
					editRepository(getSelectedRepositories().get(0));
				}
			}
		});

		filterTextfield = new JTextField();
		filterTextfield.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				filterRepositories(filterTextfield.getText());
			}
		});
		filterTextfield.addKeyListener(new KeyAdapter() {
			@Override
			public void keyReleased(KeyEvent e) {
				filterRepositories(filterTextfield.getText());
			}
		});

		JPanel repositoryFilterPanel = new JPanel(new BorderLayout(Utils.MARGIN, Utils.MARGIN));
		repositoryFilterPanel.add(new JLabel(Translation.get("gb.filter")), BorderLayout.WEST);
		repositoryFilterPanel.add(filterTextfield, BorderLayout.CENTER);

		JPanel repositoryTablePanel = new JPanel(new BorderLayout(Utils.MARGIN, Utils.MARGIN));
		repositoryTablePanel.add(repositoryFilterPanel, BorderLayout.NORTH);
		repositoryTablePanel.add(new JScrollPane(table), BorderLayout.CENTER);

		JPanel repositoryControls = new JPanel(new FlowLayout(FlowLayout.CENTER, Utils.MARGIN, 0));
		repositoryControls.add(clearCache);
		repositoryControls.add(refreshRepositories);
		repositoryControls.add(browseRepository);
		repositoryControls.add(createRepository);
		repositoryControls.add(editRepository);
		repositoryControls.add(delRepository);
		repositoryControls.add(subscribeRepository);
		repositoryControls.add(logRepository);
		repositoryControls.add(searchRepository);

		setLayout(new BorderLayout(Utils.MARGIN, Utils.MARGIN));
		header = new HeaderPanel(Translation.get("gb.repositories"), "git-orange-16x16.png");
		add(header, BorderLayout.NORTH);
		add(repositoryTablePanel, BorderLayout.CENTER);
		add(repositoryControls, BorderLayout.SOUTH);
	}

	@Override
	public void requestFocus() {
		filterTextfield.requestFocus();
	}

	@Override
	public Insets getInsets() {
		return Utils.INSETS;
	}

	private void setRepositoryRenderer(RepositoriesTableModel.Columns col,
			TableCellRenderer renderer, int maxWidth) {
		String name = table.getColumnName(col.ordinal());
		table.getColumn(name).setCellRenderer(renderer);
		if (maxWidth > 0) {
			table.getColumn(name).setMinWidth(maxWidth);
			table.getColumn(name).setMaxWidth(maxWidth);
		}
	}

	protected abstract void subscribeFeeds(List<FeedModel> feeds);

	protected abstract void updateUsersTable();

	protected abstract void updateTeamsTable();

	protected void disableManagement() {
		clearCache.setVisible(false);
		createRepository.setVisible(false);
		editRepository.setVisible(false);
		delRepository.setVisible(false);
	}

	protected void updateTable(boolean pack) {
		tableModel.list.clear();
		tableModel.list.addAll(gitblit.getRepositories());
		tableModel.fireTableDataChanged();
		header.setText(Translation.get("gb.repositories") + " (" + gitblit.getRepositories().size()
				+ ")");
		if (pack) {
			Utils.packColumns(table, Utils.MARGIN);
		}
	}

	private void filterRepositories(final String fragment) {
		if (StringUtils.isEmpty(fragment)) {
			table.setRowSorter(defaultSorter);
			return;
		}
		RowFilter<RepositoriesTableModel, Object> containsFilter = new RowFilter<RepositoriesTableModel, Object>() {
			@Override
			public boolean include(Entry<? extends RepositoriesTableModel, ? extends Object> entry) {
				for (int i = entry.getValueCount() - 1; i >= 0; i--) {
					if (entry.getStringValue(i).toLowerCase().contains(fragment.toLowerCase())) {
						return true;
					}
				}
				return false;
			}
		};
		TableRowSorter<RepositoriesTableModel> sorter = new TableRowSorter<RepositoriesTableModel>(
				tableModel);
		sorter.setRowFilter(containsFilter);
		table.setRowSorter(sorter);
	}

	private List<RepositoryModel> getSelectedRepositories() {
		List<RepositoryModel> repositories = new ArrayList<RepositoryModel>();
		for (int viewRow : table.getSelectedRows()) {
			int modelRow = table.convertRowIndexToModel(viewRow);
			RepositoryModel model = tableModel.list.get(modelRow);
			repositories.add(model);
		}
		return repositories;
	}

	protected void refreshRepositories() {
		GitblitWorker worker = new GitblitWorker(RepositoriesPanel.this,
				RpcRequest.LIST_REPOSITORIES) {
			@Override
			protected Boolean doRequest() throws IOException {
				gitblit.refreshRepositories();
				return true;
			}

			@Override
			protected void onSuccess() {
				updateTable(false);
			}
		};
		worker.execute();
	}

	protected void clearCache() {
		GitblitWorker worker = new GitblitWorker(RepositoriesPanel.this,
				RpcRequest.CLEAR_REPOSITORY_CACHE) {
			@Override
			protected Boolean doRequest() throws IOException {
				if (gitblit.clearRepositoryCache()) {
					gitblit.refreshRepositories();
					return true;
				}
				return false;
			}

			@Override
			protected void onSuccess() {
				updateTable(false);
			}
		};
		worker.execute();
	}

	/**
	 * Displays the create repository dialog and fires a SwingWorker to update
	 * the server, if appropriate.
	 *
	 */
	protected void createRepository() {
		EditRepositoryDialog dialog = new EditRepositoryDialog(gitblit.getProtocolVersion());
		dialog.setLocationRelativeTo(RepositoriesPanel.this);
		dialog.setAccessRestriction(gitblit.getDefaultAccessRestriction());
		dialog.setAuthorizationControl(gitblit.getDefaultAuthorizationControl());
		dialog.setUsers(null, gitblit.getUsernames(), null);
		dialog.setTeams(gitblit.getTeamnames(), null);
		dialog.setRepositories(gitblit.getRepositories());
		dialog.setFederationSets(gitblit.getFederationSets(), null);
		dialog.setIndexedBranches(new ArrayList<String>(Arrays.asList(Constants.DEFAULT_BRANCH)), null);
		dialog.setPreReceiveScripts(gitblit.getPreReceiveScriptsUnused(null),
				gitblit.getPreReceiveScriptsInherited(null), null);
		dialog.setPostReceiveScripts(gitblit.getPostReceiveScriptsUnused(null),
				gitblit.getPostReceiveScriptsInherited(null), null);
		dialog.setVisible(true);
		final RepositoryModel newRepository = dialog.getRepository();
		final List<RegistrantAccessPermission> permittedUsers = dialog.getUserAccessPermissions();
		final List<RegistrantAccessPermission> permittedTeams = dialog.getTeamAccessPermissions();
		if (newRepository == null) {
			return;
		}

		GitblitWorker worker = new GitblitWorker(this, RpcRequest.CREATE_REPOSITORY) {

			@Override
			protected Boolean doRequest() throws IOException {
				boolean success = gitblit.createRepository(newRepository, permittedUsers,
						permittedTeams);
				if (success) {
					gitblit.refreshRepositories();
					if (permittedUsers.size() > 0) {
						gitblit.refreshUsers();
					}
					if (permittedTeams.size() > 0) {
						gitblit.refreshTeams();
					}
				}
				return success;
			}

			@Override
			protected void onSuccess() {
				updateTable(false);
				updateUsersTable();
				updateTeamsTable();
			}

			@Override
			protected void onFailure() {
				showFailure("Failed to execute request \"{0}\" for repository \"{1}\".",
						getRequestType(), newRepository.name);
			}
		};
		worker.execute();
	}

	/**
	 * Displays the edit repository dialog and fires a SwingWorker to update the
	 * server, if appropriate.
	 *
	 * @param repository
	 */
	protected void editRepository(final RepositoryModel repository) {
		EditRepositoryDialog dialog = new EditRepositoryDialog(gitblit.getProtocolVersion(),
				repository);
		dialog.setLocationRelativeTo(RepositoriesPanel.this);
		List<String> usernames = gitblit.getUsernames();
		List<RegistrantAccessPermission> members = gitblit.getUserAccessPermissions(repository);
		dialog.setUsers(new ArrayList<String>(repository.owners), usernames, members);
		dialog.setTeams(gitblit.getTeamnames(), gitblit.getTeamAccessPermissions(repository));
		dialog.setRepositories(gitblit.getRepositories());
		dialog.setFederationSets(gitblit.getFederationSets(), repository.federationSets);
		List<String> allLocalBranches = new ArrayList<String>();
		allLocalBranches.add(Constants.DEFAULT_BRANCH);
		allLocalBranches.addAll(repository.getLocalBranches());
		dialog.setIndexedBranches(allLocalBranches, repository.indexedBranches);
		dialog.setPreReceiveScripts(gitblit.getPreReceiveScriptsUnused(repository),
				gitblit.getPreReceiveScriptsInherited(repository), repository.preReceiveScripts);
		dialog.setPostReceiveScripts(gitblit.getPostReceiveScriptsUnused(repository),
				gitblit.getPostReceiveScriptsInherited(repository), repository.postReceiveScripts);
		if (gitblit.getSettings().hasKey(Keys.groovy.customFields)) {
			Map<String, String> map = gitblit.getSettings().get(Keys.groovy.customFields).getMap();
			dialog.setCustomFields(repository, map);
		}
		dialog.setVisible(true);
		final RepositoryModel revisedRepository = dialog.getRepository();
		final List<RegistrantAccessPermission> permittedUsers = dialog.getUserAccessPermissions();
		final List<RegistrantAccessPermission> permittedTeams = dialog.getTeamAccessPermissions();
		if (revisedRepository == null) {
			return;
		}

		GitblitWorker worker = new GitblitWorker(this, RpcRequest.EDIT_REPOSITORY) {

			@Override
			protected Boolean doRequest() throws IOException {
				boolean success = gitblit.updateRepository(repository.name, revisedRepository,
						permittedUsers, permittedTeams);
				if (success) {
					gitblit.refreshRepositories();
					gitblit.refreshUsers();
					gitblit.refreshTeams();
				}
				return success;
			}

			@Override
			protected void onSuccess() {
				updateTable(false);
				updateUsersTable();
				updateTeamsTable();
			}

			@Override
			protected void onFailure() {
				showFailure("Failed to execute request \"{0}\" for repository \"{1}\".",
						getRequestType(), repository.name);
			}
		};
		worker.execute();
	}

	protected void deleteRepositories(final List<RepositoryModel> repositories) {
		if (repositories == null || repositories.size() == 0) {
			return;
		}
		StringBuilder message = new StringBuilder("Delete the following repositories?\n\n");
		for (RepositoryModel repository : repositories) {
			message.append(repository.name).append("\n");
		}
		int result = JOptionPane.showConfirmDialog(RepositoriesPanel.this, message.toString(),
				"Delete Repositories?", JOptionPane.YES_NO_OPTION);
		if (result == JOptionPane.YES_OPTION) {
			GitblitWorker worker = new GitblitWorker(this, RpcRequest.DELETE_REPOSITORY) {
				@Override
				protected Boolean doRequest() throws IOException {
					boolean success = true;
					for (RepositoryModel repository : repositories) {
						success &= gitblit.deleteRepository(repository);
					}
					if (success) {
						gitblit.refreshRepositories();
						gitblit.refreshUsers();
						gitblit.refreshTeams();
					}
					return success;
				}

				@Override
				protected void onSuccess() {
					updateTable(false);
					updateUsersTable();
					updateTeamsTable();
				}

				@Override
				protected void onFailure() {
					showFailure("Failed to delete specified repositories!");
				}
			};
			worker.execute();
		}
	}

	private void showSearchDialog(boolean isSearch, final RepositoryModel repository) {
		final SearchDialog dialog = new SearchDialog(gitblit, isSearch);
		if (repository != null) {
			dialog.selectRepository(repository);
		}
		dialog.setLocationRelativeTo(this);
		dialog.setVisible(true);
	}
}
