/*******************************************************************************
 * Copyright (c) 2000, 2018 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Brock Janiczak <brockj@tpg.com.au> - Bug 182267 "Add Date..." button shouldn't be visible in merge wizard
 *******************************************************************************/
package org.eclipse.team.internal.ccvs.ui.tags;

import java.util.*;
import java.util.List;

import org.eclipse.jface.action.*;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.operation.IRunnableContext;
import org.eclipse.jface.viewers.*;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.*;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.*;
import org.eclipse.team.internal.ccvs.core.CVSTag;
import org.eclipse.team.internal.ccvs.core.ICVSRepositoryLocation;
import org.eclipse.team.internal.ccvs.ui.CVSUIMessages;
import org.eclipse.team.internal.ccvs.ui.CVSUIPlugin;
import org.eclipse.team.internal.ccvs.ui.repo.NewDateTagAction;
import org.eclipse.team.internal.ccvs.ui.repo.RepositoryManager;
import org.eclipse.team.internal.ccvs.ui.tags.TagSourceWorkbenchAdapter.ProjectElementComparator;
import org.eclipse.team.internal.ui.PixelConverter;
import org.eclipse.team.internal.ui.SWTUtils;
import org.eclipse.team.internal.ui.actions.TeamAction;
import org.eclipse.team.internal.ui.dialogs.DialogArea;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.model.WorkbenchContentProvider;
import org.eclipse.ui.model.WorkbenchLabelProvider;
import org.eclipse.ui.part.PageBook;

/**
 * A dialog area that displays a list of tags for selection and supports
 * filtering of the displayed tags.
 */
public class TagSelectionArea extends DialogArea {
	
	private static int COLUMN_TRIM = "carbon".equals(SWT.getPlatform()) ? 24 : 3; //$NON-NLS-1$
	
	private static int ICON_WIDTH = 40; 
	
	/*
	 * Please see bug 184660
	 */
	private static final int SAFETY_MARGIN = 50;
	
	/*
	 * Property constant which identifies the selected tag or
	 * null if no tag is selected
	 */
	public static final String SELECTED_TAG = "selectedTag"; //$NON-NLS-1$
	
	/*
	 * Property constant which indicates that a tag has been selected in such 
	 * a way as to indicate that this is the desired tag (e.g double-click)
	 */
	public static final String OPEN_SELECTED_TAG = "openSelectedTag";  //$NON-NLS-1$
	
	/*
	 * Constants used to configure which tags are shown
	 */
	public static final int INCLUDE_HEAD_TAG = TagSourceWorkbenchAdapter.INCLUDE_HEAD_TAG;
	public static final int INCLUDE_BASE_TAG = TagSourceWorkbenchAdapter.INCLUDE_BASE_TAG;
	public static final int INCLUDE_BRANCHES = TagSourceWorkbenchAdapter.INCLUDE_BRANCHES;
	public static final int INCLUDE_VERSIONS = TagSourceWorkbenchAdapter.INCLUDE_VERSIONS;
	public static final int INCLUDE_DATES = TagSourceWorkbenchAdapter.INCLUDE_DATES;
	public static final int INCLUDE_ALL_TAGS = TagSourceWorkbenchAdapter.INCLUDE_ALL_TAGS;
	
	private String tagAreaLabel;
	private final int includeFlags;
	private CVSTag selection;
	private String helpContext;
	private Text filterText;
	private TagSource tagSource;
	private final Shell shell;
	private TagRefreshButtonArea tagRefreshArea;
	private final TagSource.ITagSourceChangeListener listener = source -> {
		Shell shell = getShell();
		if (!shell.isDisposed()) {
			shell.getDisplay().syncExec(() -> refresh());
		}
	};
	private final DisposeListener disposeListener = e -> {
		if (tagSource != null)
			tagSource.removeListener(listener);
	};

	private PageBook switcher;
	private TreeViewer tagTree;
	private TableViewer tagTable;
	private boolean treeVisible = true;
	private boolean includeFilterInputArea = true;
	private String filterPattern = ""; //$NON-NLS-1$

	private IRunnableContext context;
	
	public TagSelectionArea(Shell shell, TagSource tagSource, int includeFlags, String helpContext) {
		this.shell = shell;
		this.includeFlags = includeFlags;
		this.helpContext = helpContext;
		this.tagSource = tagSource;
		setSelection(null);
	}

	@Override
	public void createArea(Composite parent) {
		initializeDialogUnits(parent);
		Dialog.applyDialogFont(parent);
		final PixelConverter converter= new PixelConverter(parent);
		
		// Create a composite for the entire area
		Composite composite= new Composite(parent, SWT.NONE);
		composite.setLayoutData(SWTUtils.createHVFillGridData());
		composite.setLayout(SWTUtils.createGridLayout(1, converter, SWTUtils.MARGINS_NONE));
		
		// Add F1 help
		if (helpContext != null) {
			PlatformUI.getWorkbench().getHelpSystem().setHelp(composite, helpContext);
		}
		
		// Create the tree area and refresh buttons with the possibility to add stuff in between
		createTagDisplayArea(composite);	
		createCustomArea(composite);
		createRefreshButtons(composite);
		
		Dialog.applyDialogFont(parent);
		updateTagDisplay(true);
	}

	private void createTagDisplayArea(Composite parent) {
		Composite inner = createGrabbingComposite(parent, 1);
		if (isIncludeFilterInputArea()) {
			createFilterInput(inner);
			createWrappingLabel(inner, CVSUIMessages.TagSelectionArea_0, 1); 
		} else {
			createWrappingLabel(inner, NLS.bind(CVSUIMessages.TagSelectionArea_1, new String[] { getTagAreaLabel() }), 1);  
		}
		switcher = new PageBook(inner, SWT.NONE);
		GridData gridData = new GridData(GridData.FILL_BOTH);
		gridData.heightHint = 0;
		gridData.widthHint = 0;
		switcher.setLayoutData(gridData);
		tagTree = createTree(switcher);
		tagTable = createTable(switcher);
	}

	private void createFilterInput(Composite inner) {
		createWrappingLabel(inner, NLS.bind(CVSUIMessages.TagSelectionArea_2, new String[] { getTagAreaLabel() }), 1); 
		filterText = createText(inner, 1);
		filterText.addModifyListener(e -> setFilter(filterText.getText()));
		filterText.addKeyListener(new KeyListener() {
			@Override
			public void keyPressed(KeyEvent e) {
				if (e.keyCode == SWT.ARROW_DOWN && e.stateMask == 0) {			
					tagTable.getControl().setFocus();
				}
			}
			@Override
			public void keyReleased(KeyEvent e) {
				// Ignore
			}
		});
	}

	/**
	 * Return the label that should be used for the tag area.
	 * It should not have any trailing punctuations as the tag area
	 * may position it differently depending on whether the filter
	 * text input is included in the area.
	 * @return the tag area label
	 */
	public String getTagAreaLabel() {
		if (tagAreaLabel == null)
			tagAreaLabel = CVSUIMessages.TagSelectionArea_3; 
		return tagAreaLabel;
	}

	/**
	 * Set the label that should be used for the tag area.
	 * It should not have any trailing punctuations as the tag area
	 * may position it differently depending on whether the filter
	 * text input is included in the area.
	 * @param tagAreaLabel the tag area label
	 */
	public void setTagAreaLabel(String tagAreaLabel) {
		this.tagAreaLabel = tagAreaLabel;
	}
	
	/**
	 * Update the tag display to show the tags that match the
	 * include flags and the filter entered by the user.
	 */
	protected void updateTagDisplay(boolean firstTime) {
		String filter = getFilterString();
		if ((filter != null && filter.length() > 0) || isTableOnly()) {
			// Show the table and filter it accordingly
			try {
				switcher.setRedraw(false);
				treeVisible = false;
				switcher.showPage(tagTable.getControl());
				FilteredTagList list = (FilteredTagList)tagTable.getInput();
				list.setPattern(filter);
				tagTable.refresh();
				int maxWidth = getMaxWidth(list.getChildren(null));
				if (maxWidth > 0) {
					maxWidth = maxWidth + ICON_WIDTH + COLUMN_TRIM + SAFETY_MARGIN; /* space for the tag icon */
					tagTable.getTable().getColumn(0).setWidth(maxWidth);
				}
				if (filterText == null || filter == null || filter.length() == 0) {
					setSelection(selection);
				} else {
					// Only set the top selection if there is a filter from the filter text
					// of this area. This is done to avoid selection loops
					selectTopElement();
				}
			} finally {
				switcher.setRedraw(true);
			}
		} else {
			// Show the tree
			if (!isTreeVisible() || firstTime) {
				try {
					switcher.setRedraw(false);
					treeVisible = true;
					switcher.showPage(tagTree.getControl());
					tagTree.refresh();
					setSelection(selection);
				} finally {
					switcher.setRedraw(true);
				}
			}
		}
	}
	
	private int getMaxWidth(Object[] children) {
		PixelConverter converter = new PixelConverter(tagTable.getTable());
		int maxWidth = 0;
		for (int i = 0; i < children.length; i++) {
			Object object = children[i];
			if (object instanceof TagElement) {
				TagElement tag = (TagElement) object;
				int width = tag.getTag().getName().length();
				if (width > maxWidth) {
					maxWidth = width;
				}
			}
		}
		return converter.convertWidthInCharsToPixels(maxWidth);
	}

	/**
	 * Return whether only a table should be used
	 * @return whether only a table should be used
	 */
	protected boolean isTableOnly() {
		return (includeFlags == INCLUDE_VERSIONS) || (includeFlags == INCLUDE_BRANCHES);
	}

	private String getFilterString() {
		return filterPattern;
	}

	/*
	 * Select the top element in the tag table
	 */
	private void selectTopElement() {
		if (tagTable.getTable().getItemCount() > 0) {
			TableItem item = tagTable.getTable().getItem(0);
			tagTable.getTable().setSelection(new TableItem[] { item });
			tagTable.setSelection(tagTable.getSelection());
		}   
	}

	private FilteredTagList createFilteredInput() {
		return new FilteredTagList(tagSource, TagSource.convertIncludeFlaqsToTagTypes(includeFlags));
	}
	
	private Text createText(Composite parent, int horizontalSpan) {
		Text text = new Text(parent, SWT.SEARCH);
		GridData data = new GridData();
		data.horizontalSpan = horizontalSpan;
		data.horizontalAlignment = GridData.FILL;
		data.grabExcessHorizontalSpace = true;
		data.widthHint= 0;
		text.setLayoutData(data);
		return text;
	}

	protected void createRefreshButtons(Composite parent) {
		tagSource.addListener(listener);
		parent.addDisposeListener(disposeListener);
		Listener listener = null;
		if ((includeFlags & TagSourceWorkbenchAdapter.INCLUDE_DATES) != 0) {
			listener = event -> {
				CVSTag dateTag = NewDateTagAction.getDateTag(getShell(), getLocation());
				addDateTag(dateTag);
			};
		}
		tagRefreshArea = new TagRefreshButtonArea(shell, tagSource, listener);
		if (context != null)
			tagRefreshArea.setRunnableContext(context);
		tagRefreshArea.createArea(parent);
	}

	protected void createTreeMenu(TreeViewer tagTree) {
		if ((includeFlags & TagSourceWorkbenchAdapter.INCLUDE_DATES) != 0) {
			// Create the popup menu
			MenuManager menuMgr = new MenuManager();
			Tree tree = tagTree.getTree();
			Menu menu = menuMgr.createContextMenu(tree);
			menuMgr.addMenuListener(manager -> addMenuItemActions(manager));
			menuMgr.setRemoveAllWhenShown(true);
			tree.setMenu(menu);
		}
	}

	/**
	 * Create aq custom area that is below the tag selection area but above the refresh busson group
	 * @param parent
	 */
	protected void createCustomArea(Composite parent) {
		// No default custom area
	}
	
	protected TreeViewer createTree(Composite parent) {
		Tree tree = new Tree(parent, SWT.SINGLE | SWT.BORDER);
		GridData data = new GridData(GridData.FILL_BOTH);
		tree.setLayoutData(data);
		TreeViewer result = new TreeViewer(tree);
		initialize(result);
		result.getControl().addKeyListener(new KeyListener() {
			@Override
			public void keyPressed(KeyEvent event) {
				handleKeyPressed(event);
			}
			@Override
			public void keyReleased(KeyEvent event) {
				handleKeyReleased(event);
			}
		});
		result.setInput(createUnfilteredInput());
		createTreeMenu(result);
		return result;
	}

	protected TableViewer createTable(Composite parent) {
		Table table = new Table(parent, SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER | SWT.SINGLE | SWT.FULL_SELECTION);
		GridData data = new GridData(GridData.FILL_BOTH);
		table.setLayoutData(data);
		TableLayout layout = new TableLayout();
		layout.addColumnData(new ColumnWeightData(100));
		table.setLayout(layout);
		new TableColumn(table, SWT.NONE);
		TableViewer viewer = new TableViewer(table);
		initialize(viewer);
		viewer.setInput(createFilteredInput());
		return viewer;

	}

	private void initialize(StructuredViewer viewer) {
		viewer.setContentProvider(new WorkbenchContentProvider());
		viewer.setLabelProvider(new WorkbenchLabelProvider());
		viewer.setComparator(new ProjectElementComparator());
		viewer.addSelectionChangedListener(event -> handleSelectionChange());
		// select and close on double click
		// To do: use defaultselection instead of double click
		viewer.getControl().addMouseListener(new MouseAdapter() {
			@Override
			public void mouseDoubleClick(MouseEvent e) {
				CVSTag tag = internalGetSelectedTag();
				if (tag != null) {
					firePropertyChangeChange(OPEN_SELECTED_TAG, null, tag);
				}
			}
		});
	}

	private Object createUnfilteredInput() {
		return TagSourceWorkbenchAdapter.createInput(tagSource, includeFlags);
	}

	public void handleKeyPressed(KeyEvent event) {
		if (event.character == SWT.DEL && event.stateMask == 0) {			
			deleteDateTag();
		}
	}
	private void deleteDateTag() {
		TagElement[] selectedDateTagElements = getSelectedDateTagElement();
		if (selectedDateTagElements.length == 0) return;
		for(int i = 0; i < selectedDateTagElements.length; i++){
			RepositoryManager mgr = CVSUIPlugin.getPlugin().getRepositoryManager();
			CVSTag tag = selectedDateTagElements[i].getTag();
			if(tag.getType() == CVSTag.DATE){
				mgr.removeDateTag(getLocation(),tag);
			}				
		}
		tagTree.refresh();
		handleSelectionChange();
	}
	
	/**
	 * Returns the selected date tag elements
	 */
	private TagElement[] getSelectedDateTagElement() {
		ArrayList<Object> dateTagElements = null;
		IStructuredSelection selection = tagTree.getStructuredSelection();
		if (selection!=null && !selection.isEmpty()) {
			dateTagElements = new ArrayList<>();
			Iterator elements = selection.iterator();
			while (elements.hasNext()) {
				Object next = TeamAction.getAdapter(elements.next(), TagElement.class);
				if (next instanceof TagElement) {
					if(((TagElement)next).getTag().getType() == CVSTag.DATE){
						dateTagElements.add(next);
					}
				}
			}
		}
		if (dateTagElements != null && !dateTagElements.isEmpty()) {
			TagElement[] result = new TagElement[dateTagElements.size()];
			dateTagElements.toArray(result);
			return result;
		}
		return new TagElement[0];
	}
	private void addDateTag(CVSTag tag){
		if(tag == null) return;
		List<CVSTag> dateTags = new ArrayList<>();
		ICVSRepositoryLocation location = getLocation();
		dateTags.addAll(Arrays.asList(CVSUIPlugin.getPlugin().getRepositoryManager().getDateTags(location)));
		if(!dateTags.contains( tag)){
			CVSUIPlugin.getPlugin().getRepositoryManager().addDateTag(location, tag);
		}
		try {
			tagTree.getControl().setRedraw(false);
			tagTree.refresh();
			setSelection(tag);
		} finally {
			tagTree.getControl().setRedraw(true);
		}
		handleSelectionChange();
	}
	private void addMenuItemActions(IMenuManager manager) {
		manager.add(new Action(CVSUIMessages.TagSelectionDialog_0) { 
			@Override
			public void run() {
				CVSTag dateTag = NewDateTagAction.getDateTag(getShell(), getLocation());
				addDateTag(dateTag);
			}
		});
		if(getSelectedDateTagElement().length > 0){
			manager.add(new Action(CVSUIMessages.TagSelectionDialog_1) { 
				@Override
				public void run() {
					deleteDateTag();
				}
			});			
		}
	}

	protected void handleKeyReleased(KeyEvent event) {
	}
	
	/**
	 * handle a selection change event from the visible tag display
	 * (which could be either the table or the tree).
	 */
	protected void handleSelectionChange() {
		CVSTag newSelection = internalGetSelectedTag();
		if (selection != null && newSelection != null && selection.equals(newSelection)) {
			// the selection hasn't change so return
			return;
		}
		CVSTag oldSelection = selection;
		selection = newSelection;
		firePropertyChangeChange(SELECTED_TAG, oldSelection, selection);
	}
	
	private CVSTag internalGetSelectedTag() {
		IStructuredSelection selection;
		if (isTreeVisible()) {
			selection = tagTree.getStructuredSelection();
		} else {
			selection = tagTable.getStructuredSelection();
		}
		Object o = selection.getFirstElement();
		if (o instanceof TagElement)
			return ((TagElement)o).getTag();
		return null;
	}
	
	private boolean isTreeVisible() {
		return treeVisible;
	}

	private ICVSRepositoryLocation getLocation(){
		return tagSource.getLocation();
	}
	public CVSTag getSelection() {
		return selection;
	}
	public Shell getShell() {
		return shell;
	}

	/**
	 * Set the focus to the filter text widget
	 */
	public void setFocus() {
		if (filterText != null)
			filterText.setFocus();
		else if (switcher != null)
			switcher.setFocus();
			
		// Refresh in case tags were added since the last time the area had focus
		refresh();
	}

	/**
	 * Select the given tag
	 * @param selectedTag the tag to be selected
	 */
	public void setSelection(CVSTag selectedTag) {
		if (isTreeVisible())
			if (tagTree != null && !tagTree.getControl().isDisposed()) {
				// TODO: Hack to instantiate the model before revealing the selection
				tagTree.expandToLevel(2);
				tagTree.collapseAll();
				// Reveal the selection
				tagTree.reveal(new TagElement(selectedTag));
				tagTree.setSelection(new StructuredSelection(new TagElement(selectedTag)));
			}
		else
			if (tagTable != null && !tagTable.getControl().isDisposed()) {
				tagTable.setSelection(new StructuredSelection(new TagElement(selectedTag)));
			}
	}

	/**
	 * Refresh the state of the tag selection area
	 */
	public void refresh() {
		if (isTreeVisible()) {
			if (tagTree != null && !tagTree.getControl().isDisposed()) {
				tagTree.refresh();
			}
		} else {
			if (tagTable != null && !tagTable.getControl().isDisposed()) {
				tagTable.refresh();
			}
		}
	}
	
	public void refreshTagList() {
		tagRefreshArea.refresh(true);
	}

	/**
	 * Set the enablement state of the area
	 * @param enabled the enablement state
	 */
	public void setEnabled(boolean enabled) {
		if (filterText != null)
			filterText.setEnabled(enabled);
		tagTree.getControl().setEnabled(enabled);
		tagTable.getControl().setEnabled(enabled);
	}
	
	/**
	 * Set the tag source from which the displayed tags are determined
	 * @param tagSource the source of the tags being displayed
	 */
	public void setTagSource(TagSource tagSource) {
		if (this.tagSource != null) {
			this.tagSource.removeListener(listener);
		}
		this.tagSource = tagSource;
		this.tagSource.addListener(listener);
		tagRefreshArea.setTagSource(this.tagSource);
		setTreeAndTableInput();
	}

	private void setTreeAndTableInput() {
		if (tagTree != null) {
			tagTree.setInput(createUnfilteredInput());
		}
		if (tagTable != null) {
			tagTable.setInput(createFilteredInput());
		}
		
	}

	/**
	 * Set whether the input filter text is to be included in the tag selection area.
	 * If excluded, clientscan still set the filter text directly using
	 * <code>setFilter</code>.
	 * @param include whether filter text input should be included
	 */
	public void setIncludeFilterInputArea(boolean include) {
		includeFilterInputArea = include;
	}
	
	/**
	 * Return whether the input filter text is to be included in the tag selection area.
	 * If excluded, clientscan still set the filter text directly using
	 * <code>setFilter</code>.
	 * @return whether filter text input should be included
	 */
	public boolean isIncludeFilterInputArea() {
		return includeFilterInputArea;
	}

	/**
	 * Set the text used to filter the tag list.
	 * @param filter the filter pattern
	 */
	public void setFilter(String filter) {
		this.filterPattern = filter;
		updateTagDisplay(false);
	}
	
	public void setRunnableContext(IRunnableContext context) {
		this.context = context;
		if (tagRefreshArea != null)
			tagRefreshArea.setRunnableContext(context);
	}
}
