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

import java.io.*;
import com.ibm.icu.text.DateFormat;
import com.ibm.icu.text.MessageFormat;
import java.util.ArrayList;
import com.ibm.icu.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.ResourceBundle;

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, IEncodedStreamContentAccessor, IModificationDate {
		IFile fFile;
		IFileState fFileState;

		HistoryInput(IFile file, IFileState fileState) {
			fFile= file;
			fFileState= fileState;
		}
		@Override
		public InputStream getContents() throws CoreException {
			return new BufferedInputStream(fFileState.getContents());
		}
		@Override
		public String getCharset() {
			String charset= null;
			try {
				charset= fFileState.getCharset();
			} catch (CoreException e) {
				// fall through
			}
			if (charset == null)
				charset= Utilities.getCharset(fFile);
			return charset;
		}
		@Override
		public String getName() {
			return fFile.getName();
		}
		@Override
		public String getType() {
			return fFile.getFileExtension();
		}
		@Override
		public Image getImage() {
			return CompareUI.getImage(fFile);
		}
		@Override
		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) {
					// NeedWork
				}
			}
			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.png"); //$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.png"); //$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, 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]= 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();

				// ignore a recently deleted file at the same path as the
				// container
				if (path.equals(prefix))
					continue;

				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;
	}

	@Override
	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() {
				@Override
				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() {
				@Override
				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() {
				@Override
				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) {
			@Override
			protected Viewer getViewer(Viewer oldViewer, Object input) {
				return CompareUI.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, 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, 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, date);
	}

	/* (non-Javadoc)
	 * Method declared on Dialog.
	 */
	@Override
	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);
	}
}
