/*******************************************************************************
 * Copyright (c) 2000, 2003 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.compare.internal;

import java.io.*;
import java.text.*;
import java.util.*;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;

import org.eclipse.jface.dialogs.*;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.Viewer;

import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;

import org.eclipse.compare.*;


public class AddFromHistoryDialog extends ResizableDialog {
	
	static class HistoryInput implements ITypedElement, IStreamContentAccessor, IModificationDate {
		IFile fFile;
		IFileState fFileState;
		
		HistoryInput(IFile file, IFileState fileState) {
			fFile= file;
			fFileState= fileState;
		}
		public InputStream getContents() throws CoreException {
			return new BufferedInputStream(fFileState.getContents());
		}
		public String getName() {
			return fFile.getName();
		}
		public String getType() {
			return fFile.getFileExtension();
		}
		public Image getImage() {
			return CompareUI.getImage(fFile);
		}
		public long getModificationDate() {
			return fFileState.getModificationTime();
		}
	}
	
	static class FileHistory {
		private IFile fFile;
		private IFileState[] fStates;
		private int fSelected;
		
		FileHistory(IFile file) {
			fFile= file;
		}
		
		IFile getFile() {
			return fFile;
		}
		
		IFileState[] getStates() {
			if (fStates == null) {
				try {
					fStates= fFile.getHistory(new NullProgressMonitor());
				} catch (CoreException ex) {
				}
			}
			return fStates;
		}
		
		IFileState getSelectedState() {
			return getStates()[fSelected];
		}
		
		void setSelected(IFileState state) {
			for (int i= 0; i < fStates.length; i++) {
				if (fStates[i] == state) {
					fSelected= i;
					return;
				}
			}
		}
		
		HistoryInput getHistoryInput() {
			return new HistoryInput(fFile, getSelectedState());
		}
		
		boolean isSelected(int index) {
			return index == fSelected;
		}
	}

	private CompareConfiguration fCompareConfiguration;
	private ArrayList fArrayList= new ArrayList();
	private FileHistory fCurrentFileHistory;

	// SWT controls
	private CompareViewerSwitchingPane fContentPane;
	private Button fCommitButton;
	private Table fMemberTable;
	private CompareViewerPane fMemberPane;
	private Tree fEditionTree;
	private CompareViewerPane fEditionPane;
	private Image fDateImage;
	private Image fTimeImage;


	public AddFromHistoryDialog(Shell parent, ResourceBundle bundle) {
		super(parent, bundle);
					
		String iconName= Utilities.getString(fBundle, "dateIcon", "obj16/day_obj.gif"); //$NON-NLS-2$ //$NON-NLS-1$
		ImageDescriptor id= CompareUIPlugin.getImageDescriptor(iconName);
		if (id != null)
			fDateImage= id.createImage();
		iconName= Utilities.getString(fBundle, "timeIcon", "obj16/resource_obj.gif"); //$NON-NLS-1$ //$NON-NLS-2$
		id= CompareUIPlugin.getImageDescriptor(iconName);
		if (id != null)
			fTimeImage= id.createImage();
	}
	
	public boolean select(IContainer root, IFile[] inputFiles) {
		
		create();	// create widgets
		
		String format= Utilities.getString(fBundle, "memberPaneTitle");	//$NON-NLS-1$
		String title= MessageFormat.format(format, new Object[] { root.getName() });
		fMemberPane.setImage(CompareUI.getImage(root));
		fMemberPane.setText(title);
		
		// sort input files
		final int count= inputFiles.length;
		final IFile[] files= new IFile[count];
		for (int i= 0; i < count; i++)
			files[i]= (IFile) inputFiles[i];
		if (count > 1)
			internalSort(files, 0, count-1);
			
		
		String prefix= root.getFullPath().toString();
		
		if (fMemberTable != null && !fMemberTable.isDisposed()) {
			for (int i= 0; i < files.length; i++) {
				IFile file= files[i];
				String path= file.getFullPath().toString();
				if (path.startsWith(prefix))
					path= path.substring(prefix.length()+1);
				TableItem ti= new TableItem(fMemberTable, SWT.NONE);
				ti.setImage(CompareUI.getImage(file));
				ti.setText(path);
				ti.setData(new FileHistory(file));
			}
		}
		
		open();
		
		return (getReturnCode() == OK) && (fArrayList.size() > 0);
	}
		
	HistoryInput[] getSelected() {
		HistoryInput[] selected= new HistoryInput[fArrayList.size()];
		Iterator iter= fArrayList.iterator();
		for (int i= 0; iter.hasNext(); i++) {
			FileHistory h= (FileHistory) iter.next();
			selected[i]= h.getHistoryInput();
		}
		return selected;
	}
				
	protected synchronized Control createDialogArea(Composite parent2) {
		
		Composite parent= (Composite) super.createDialogArea(parent2);

		getShell().setText(Utilities.getString(fBundle, "title")); //$NON-NLS-1$
		
		org.eclipse.compare.Splitter vsplitter= new org.eclipse.compare.Splitter(parent,  SWT.VERTICAL);
		vsplitter.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL
					| GridData.VERTICAL_ALIGN_FILL | GridData.GRAB_VERTICAL));

		vsplitter.addDisposeListener(
			new DisposeListener() {
				public void widgetDisposed(DisposeEvent e) {
					if (fDateImage != null)
						fDateImage.dispose();
					if (fTimeImage != null)
						fTimeImage.dispose();
				}
			}
		);
		
		// we need two panes: the left for the elements, the right one for the editions
		Splitter hsplitter= new Splitter(vsplitter,  SWT.HORIZONTAL);
		
		Composite c= new Composite(hsplitter, SWT.NONE);
		GridLayout layout= new GridLayout();
		layout.marginWidth= 0;
		layout.marginHeight= 2;
		layout.verticalSpacing= 2;
		layout.numColumns= 1;
		c.setLayout(layout);
		Label l1= new Label(c, SWT.NONE);
		l1.setText(Utilities.getString(fBundle, "memberDescription"));	//$NON-NLS-1$
		fMemberPane= new CompareViewerPane(c, SWT.BORDER | SWT.FLAT);
		GridData gd= new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL);
		fMemberPane.setLayoutData(gd);

		fMemberTable= new Table(fMemberPane, SWT.CHECK | SWT.H_SCROLL | SWT.V_SCROLL);
		fMemberTable.addSelectionListener(
			new SelectionAdapter() {
				public void widgetSelected(SelectionEvent e) {
					if (e.detail == SWT.CHECK) {
						if (e.item instanceof TableItem) {
							TableItem ti= (TableItem) e.item;
							if (ti.getChecked())
								fArrayList.add(ti.getData());
							else
								fArrayList.remove(ti.getData());
								
							if (fCommitButton != null)
								fCommitButton.setEnabled(fArrayList.size() > 0);
						}
					} else {
						handleMemberSelect(e.item);
					}
				}
			}
		);
				
		fMemberPane.setContent(fMemberTable);
		
		c= new Composite(hsplitter, SWT.NONE);
		layout= new GridLayout();
		layout.marginWidth= 0;
		layout.marginHeight= 2;
		layout.verticalSpacing= 2;
		layout.numColumns= 1;
		c.setLayout(layout);
		Label l2= new Label(c, SWT.NONE);
		l2.setText(Utilities.getString(fBundle, "editionDescription"));	//$NON-NLS-1$
		fEditionPane= new CompareViewerPane(c, SWT.BORDER | SWT.FLAT);
		gd= new GridData(GridData.FILL_HORIZONTAL | GridData.FILL_VERTICAL);
		fEditionPane.setLayoutData(gd);
		
		fEditionTree= new Tree(fEditionPane, SWT.H_SCROLL | SWT.V_SCROLL);
		fEditionTree.addSelectionListener(
			new SelectionAdapter() {
				public void widgetSelected(SelectionEvent e) {
					feedContent(e.item);
				}
			}
		);
		fEditionPane.setContent(fEditionTree);		
		
		applyDialogFont(parent); // to avoid applying font to compare viewer
		fContentPane= new CompareViewerSwitchingPane(vsplitter, SWT.BORDER | SWT.FLAT) {
			protected Viewer getViewer(Viewer oldViewer, Object input) {
				return CompareUIPlugin.findContentViewer(oldViewer, input, this, fCompareConfiguration);	
			}
		};
		vsplitter.setWeights(new int[] { 30, 70 });
		
		return parent;
	}
	
	/**
	 * Feeds selection from member viewer to edition viewer.
	 */
	private void handleMemberSelect(Widget w) {
		Object data= null;
		if (w != null)
			data= w.getData();
		if (data instanceof FileHistory) {
			
			FileHistory h= (FileHistory) data;
			fCurrentFileHistory= h;
			
			IFile file= h.getFile();
			IFileState[] states= h.getStates();
			
			fEditionPane.setImage(CompareUI.getImage(file));
			String pattern= Utilities.getString(fBundle, "treeTitleFormat"); //$NON-NLS-1$
			String title= MessageFormat.format(pattern, new Object[] { file.getName() });
			fEditionPane.setText(title);
			
			if (fEditionTree != null) {
				fEditionTree.setRedraw(false);
				fEditionTree.removeAll();
				for (int i= 0; i < states.length; i++) {
					addEdition(new HistoryInput(file, states[i]), h.isSelected(i));
				}
				fEditionTree.setRedraw(true);
			}
		} else
			fCurrentFileHistory= null;
	}
	
	/**
	 * Adds the given Pair to the edition tree.
	 * It takes care of creating tree nodes for different dates.
	 */
	private void addEdition(HistoryInput input, boolean isSelected) {
		if (fEditionTree == null || fEditionTree.isDisposed())
			return;
		
		IFileState state= input.fFileState;
		
		// find last day
		TreeItem[] days= fEditionTree.getItems();
		TreeItem lastDay= null;
		if (days.length > 0)
			lastDay= days[days.length-1];
						
		long ldate= state.getModificationTime();		
		long day= dayNumber(ldate);
		Date date= new Date(ldate);
		if (lastDay == null || day != dayNumber(((Date)lastDay.getData()).getTime())) {
			lastDay= new TreeItem(fEditionTree, SWT.NONE);
			lastDay.setImage(fDateImage);
			String df= DateFormat.getDateInstance().format(date);
			long today= dayNumber(System.currentTimeMillis());
			
			String formatKey;
			if (day == today)
				formatKey= "todayFormat"; //$NON-NLS-1$
			else if (day == today-1)
				formatKey= "yesterdayFormat"; //$NON-NLS-1$
			else
				formatKey= "dayFormat"; //$NON-NLS-1$
			String pattern= Utilities.getString(fBundle, formatKey);
			if (pattern != null)
				df= MessageFormat.format(pattern, new String[] { df });
			lastDay.setText(df);
			lastDay.setData(date);
		}
		TreeItem ti= new TreeItem(lastDay, SWT.NONE);
		ti.setImage(fTimeImage);
		ti.setText(DateFormat.getTimeInstance().format(date));
		ti.setData(input);

		if (isSelected) {
			lastDay.setExpanded(true);
			fEditionTree.setSelection(new TreeItem[] { ti });
			feedContent(ti);
		}
	}
						
	/**
	 * Returns the number of s since Jan 1st, 1970.
	 * The given date is converted to GMT and daylight saving is taken into account too.
	 */
	private long dayNumber(long date) {
		int ONE_DAY_MS= 24*60*60 * 1000; // one day in milli seconds
		
		Calendar calendar= Calendar.getInstance();
		long localTimeOffset= calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET);
		
		return (date + localTimeOffset) / ONE_DAY_MS;
	}
	
	/**
	 * Feeds the tree viewer's selection to the contentviewer
	 */
	private void feedContent(Widget w) {
		if (fContentPane != null && !fContentPane.isDisposed()) {
			Object o= w.getData();
			if (o instanceof HistoryInput) {
				HistoryInput selected= (HistoryInput) o;
				fContentPane.setInput(selected);
				fContentPane.setText(getEditionLabel(selected));
				fContentPane.setImage(fTimeImage);
				
				if (fCurrentFileHistory != null)
					fCurrentFileHistory.setSelected(selected.fFileState);
			} else {
				fContentPane.setInput(null);
			}
		}
	}
	
	protected String getEditionLabel(HistoryInput input) {
		String format= Utilities.getString(fBundle, "historyEditionLabel", null);	//$NON-NLS-1$
		if (format == null)
			format= Utilities.getString(fBundle, "editionLabel");	//$NON-NLS-1$
		if (format == null)
			format= "x{0}";	//$NON-NLS-1$
		
		long modDate= input.getModificationDate();
		String date= DateFormat.getDateTimeInstance().format(new Date(modDate));
		
		return MessageFormat.format(format, new Object[] { date });
	}
			
	/* (non-Javadoc)
	 * Method declared on Dialog.
	 */
	protected void createButtonsForButtonBar(Composite parent) {
		String buttonLabel= Utilities.getString(fBundle, "buttonLabel", IDialogConstants.OK_LABEL); //$NON-NLS-1$
		// a 'Cancel' and a 'Add' button
		fCommitButton= createButton(parent, IDialogConstants.OK_ID, buttonLabel, true);
		fCommitButton.setEnabled(false);
		createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false);
	}
	
	/**
	 * Returns true if the pathname of f1 comes after f2
	 */
	private static boolean greaterThan(IFile f1, IFile f2) {
		String[] ss1= f1.getFullPath().segments();
		String[] ss2= f2.getFullPath().segments();
		int l1= ss1.length;
		int l2= ss2.length;
		int n= Math.max(l1, l2);
		
		for (int i= 0; i < n; i++) {
			String s1= i < l1 ? ss1[i] : ""; //$NON-NLS-1$
			String s2= i < l2 ? ss2[i] : ""; //$NON-NLS-1$
			int rc= s1.compareToIgnoreCase(s2);
			if (rc != 0)
				return rc < 0;
		}
		return false;
	}
	
	private static void internalSort(IFile[] keys, int left, int right) { 
	
		int original_left= left;
		int original_right= right;
		
		IFile mid= keys[(left + right) / 2]; 
		do { 
			while (greaterThan(keys[left], mid))
				left++; 
			
			while (greaterThan(mid, keys[right]))
				right--; 
		
			if (left <= right) { 
				IFile tmp= keys[left]; 
				keys[left]= keys[right]; 
				keys[right]= tmp;			
				left++; 
				right--; 
			} 
		} while (left <= right);
		
		if (original_left < right)
			internalSort(keys, original_left, right); 
		
		if (left < original_right)
			internalSort(keys, left, original_right); 
	}
}
