/*
 * (c) Copyright IBM Corp. 2000, 2001.
 * All Rights Reserved.
 */
package org.eclipse.compare.internal.patch;

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

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

import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.jface.resource.ImageDescriptor;

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

import org.eclipse.compare.*;
import org.eclipse.compare.internal.CompareUIPlugin;
import org.eclipse.compare.internal.DiffImage;
import org.eclipse.compare.structuremergeviewer.*;


/**
 * Shows the parsed patch file and any mismatches
 * between files, hunks and the currently selected
 * resources.
 */
/* package */ class PreviewPatchPage extends WizardPage {
	
	/**
	 * Used with CompareInput
	 */
	static class HunkInput implements ITypedElement, IStreamContentAccessor {
		String fContent;
		String fType;
		
		HunkInput(String type, String s) {
			fType= type;
			fContent= s;
		}
		public Image getImage() {
			return null;
		}
		public String getName() {
			return PatchMessages.getString("PreviewPatchPage.NoName.text"); //$NON-NLS-1$
		}
		public String getType() {
			return fType;
		}
		public InputStream getContents() {
			return new ByteArrayInputStream(fContent.getBytes());
		}
	};
		
	private PatchWizard fPatchWizard;
	
	private Tree fTree;
	private Combo fStripPrefixSegments;
	private CompareViewerSwitchingPane fHunkViewer;
	private Button fIgnoreWhitespaceButton;
	private Button fReversePatchButton;
	private Text fFuzzField;
	
	private Image fNullImage;
	private Image fAddImage;
	private Image fDelImage;
	private Image fErrorImage;
	private Image fErrorAddImage;
	private Image fErrorDelImage;
	
	private CompareConfiguration fCompareConfiguration;
	
	
	/* package */ PreviewPatchPage(PatchWizard pw) {
		super("PreviewPatchPage",	//$NON-NLS-1$ 
			PatchMessages.getString("PreviewPatchPage.title"), null); //$NON-NLS-1$
		
		setMessage(PatchMessages.getString("PreviewPatchPage.message"));	//$NON-NLS-1$
		
		fPatchWizard= pw;
		//setPageComplete(false);
		
		int w= 16;
		
		ImageDescriptor addId= CompareUIPlugin.getImageDescriptor("ovr16/add_ov.gif");	//$NON-NLS-1$
		ImageDescriptor delId= CompareUIPlugin.getImageDescriptor("ovr16/del_ov.gif");	//$NON-NLS-1$

		ImageDescriptor errId= CompareUIPlugin.getImageDescriptor("ovr16/error_ov.gif");	//$NON-NLS-1$
		Image errIm= errId.createImage();
		
		fNullImage= new DiffImage(null, null, w).createImage();
		fAddImage= new DiffImage(null, addId, w).createImage();
		fDelImage= new DiffImage(null, delId, w).createImage();

		fErrorImage= new DiffImage(errIm, null, w).createImage();
		fErrorAddImage= new DiffImage(errIm, addId, w).createImage();
		fErrorDelImage= new DiffImage(errIm, delId, w).createImage();
		
		fCompareConfiguration= new CompareConfiguration();
		
		fCompareConfiguration.setLeftEditable(false);
		fCompareConfiguration.setLeftLabel(PatchMessages.getString("PreviewPatchPage.Left.title")); //$NON-NLS-1$
		
		fCompareConfiguration.setRightEditable(false);
		fCompareConfiguration.setRightLabel(PatchMessages.getString("PreviewPatchPage.Right.title")); //$NON-NLS-1$
	}
	
	/* (non-Javadoc)
	 * Method declared in WizardPage
	 */
	public void setVisible(boolean visible) {
		if (visible)
			buildTree();
		super.setVisible(visible);
	}

	Image getImage(Diff diff) {
		if (diff.fMatches) {
			switch (diff.getType()) {
			case Differencer.ADDITION:
				return fAddImage;
			case Differencer.DELETION:
				return fDelImage;
			}
			return fNullImage;
		}
		switch (diff.getType()) {
		case Differencer.ADDITION:
			return fErrorAddImage;
		case Differencer.DELETION:
			return fErrorDelImage;
		}
		return fErrorImage;
	}
	
	Image getImage(Hunk hunk) {
		if (hunk.fMatches)
			return fNullImage;
		return fErrorImage;
	}
	
	public void createControl(Composite parent) {

		Composite composite= new Composite(parent, SWT.NULL);
		composite.setLayout(new GridLayout());
		composite.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_FILL | GridData.HORIZONTAL_ALIGN_FILL));

		setControl(composite);
		
		buildPatchOptionsGroup(composite);
		
		Splitter splitter= new Splitter(composite, SWT.VERTICAL);
		splitter.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL
					| GridData.VERTICAL_ALIGN_FILL | GridData.GRAB_VERTICAL));

		
		// top pane showing diffs and hunks in a check box tree 
		fTree= new Tree(splitter, SWT.CHECK | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL);
		GridData gd= new GridData();
		gd.verticalAlignment= GridData.FILL;
		gd.horizontalAlignment= GridData.FILL;
		gd.grabExcessHorizontalSpace= true;
		gd.grabExcessVerticalSpace= true;
		fTree.setLayoutData(gd);
				
		// bottom pane showing hunks in compare viewer 
		fHunkViewer= new CompareViewerSwitchingPane(splitter, SWT.BORDER | SWT.FLAT) {
			protected Viewer getViewer(Viewer oldViewer, Object input) {
				return CompareUI.findContentViewer(oldViewer, (ICompareInput)input, this, fCompareConfiguration);
			}
		};
		gd= new GridData();
		gd.verticalAlignment= GridData.FILL;
		gd.horizontalAlignment= GridData.FILL;
		gd.grabExcessHorizontalSpace= true;
		gd.grabExcessVerticalSpace= true;
		fHunkViewer.setLayoutData(gd);
		
		// register listeners
		
		fTree.addSelectionListener(
			new SelectionAdapter() {
				public void widgetSelected(SelectionEvent e) {
					TreeItem ti= (TreeItem) e.item;
					Object data= e.item.getData();
					if (e.detail == SWT.CHECK) {
						boolean checked= ti.getChecked();
						if (data instanceof Hunk) {
							Hunk hunk= (Hunk) data;
							checked= checked && hunk.fMatches;
							//hunk.setEnabled(checked);
							ti.setChecked(checked);
							updateGrayedState(ti);
						} else if (data instanceof Diff) {
							updateCheckedState(ti);
						}
					} else {
						if (data instanceof Hunk)
							PreviewPatchPage.this.fHunkViewer.setInput(createInput((Hunk)data));
						else
							PreviewPatchPage.this.fHunkViewer.setInput(null);
					}
				}
			}
		);
		
		// creating tree's content
		buildTree();

		// WorkbenchHelp.setHelp(composite, new DialogPageContextComputer(this, PATCH_HELP_CONTEXT_ID));								
	}
	
	/**
	 *	Create the group for setting various patch options
	 */
	private void buildPatchOptionsGroup(Composite parent) {
				
		final Patcher patcher= fPatchWizard.getPatcher();
		
		Group group= new Group(parent, SWT.NONE);
		group.setText(PatchMessages.getString("PreviewPatchPage.PatchOptions.title")); //$NON-NLS-1$
		GridLayout layout= new GridLayout();
		layout.numColumns= 5;
		group.setLayout(layout);
		group.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL));
		//fPatchFileGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
	
		// 1st row
		new Label(group, SWT.NONE).setText(PatchMessages.getString("PreviewPatchPage.IgnoreSegments.text")); //$NON-NLS-1$

		fStripPrefixSegments= new Combo(group, SWT.DROP_DOWN | SWT.READ_ONLY | SWT.SIMPLE);
		int prefixCnt= patcher.getStripPrefixSegments();
		String prefix= Integer.toString(prefixCnt);
		fStripPrefixSegments.add(prefix);
		fStripPrefixSegments.setText(prefix);
		
		addSpacer(group);
		
		fReversePatchButton= new Button(group, SWT.CHECK);
		fReversePatchButton.setText(PatchMessages.getString("PreviewPatchPage.ReversePatch.text")); //$NON-NLS-1$
		
		addSpacer(group);
		
		// 2nd row
		Label l= new Label(group, SWT.NONE);
		l.setText(PatchMessages.getString("PreviewPatchPage.FuzzFactor.text")); //$NON-NLS-1$
		l.setToolTipText(PatchMessages.getString("PreviewPatchPage.FuzzFactor.tooltip")); //$NON-NLS-1$
		fFuzzField= new Text(group, SWT.BORDER);
		fFuzzField.setText("2"); //$NON-NLS-1$
		GridData gd2= new GridData(GridData.HORIZONTAL_ALIGN_CENTER);
		gd2.widthHint= 30;
		fFuzzField.setLayoutData(gd2);

		addSpacer(group);
		
		fIgnoreWhitespaceButton= new Button(group, SWT.CHECK);
		fIgnoreWhitespaceButton.setText(PatchMessages.getString("PreviewPatchPage.IgnoreWhitespace.text")); //$NON-NLS-1$
		
		addSpacer(group);
				
		// register listeners
			
		if (fStripPrefixSegments != null) 
			fStripPrefixSegments.addSelectionListener(
				new SelectionAdapter() {
					public void widgetSelected(SelectionEvent e) {
						if (patcher.setStripPrefixSegments(getStripPrefixSegments()))
							updateTree();
					}
				}
			);
		fReversePatchButton.addSelectionListener(
			new SelectionAdapter() {
				public void widgetSelected(SelectionEvent e) {
					if (patcher.setReversed(fReversePatchButton.getSelection()))
						updateTree();
				}
			}
		);
		fIgnoreWhitespaceButton.addSelectionListener(
			new SelectionAdapter() {
				public void widgetSelected(SelectionEvent e) {
					if (patcher.setIgnoreWhitespace(fIgnoreWhitespaceButton.getSelection()))
						updateTree();
				}
			}
		);
		
		fFuzzField.addModifyListener(
			new ModifyListener() {
				public void modifyText(ModifyEvent e) {
					if (patcher.setFuzz(getFuzzFactor()))
						updateTree();
				}
			}
		);
	}
		
	ICompareInput createInput(Hunk hunk) {
		
		String[] lines= hunk.fLines;
		StringBuffer left= new StringBuffer();
		StringBuffer right= new StringBuffer();
		
		for (int i= 0; i < lines.length; i++) {
			String line= lines[i];
			String rest= line.substring(1);
			switch (line.charAt(0)) {
			case ' ':
				left.append(rest);
				right.append(rest);
				break;
			case '-':
				left.append(rest);
				break;
			case '+':
				right.append(rest);
				break;
			}
		}
		
		Diff diff= hunk.fParent;
		IPath path= diff.getPath();
		String type= path.getFileExtension();
		
		return new DiffNode(new HunkInput(type, left.toString()), new HunkInput(type, right.toString()));
	}		
	
	/**
	 * Builds a tree from list of Diffs.
	 * As a side effect it calculates the maximum number of segments
	 * in all paths.
	 */
	private void buildTree() {
		setPageComplete(true);
		if (fTree != null && !fTree.isDisposed()) {
			fTree.removeAll();
			fHunkViewer.setInput(null);
			
			int length= 99;
			
			Diff[] diffs= fPatchWizard.getPatcher().getDiffs();			
			if (diffs != null) {
				for (int i= 0; i < diffs.length; i++) {
					Diff diff= diffs[i];
					TreeItem d= new TreeItem(fTree, SWT.NULL);
					d.setData(diff);
					d.setImage(getImage(diff));
					
					if (diff.fOldPath != null)
						length= Math.min(length, diff.fOldPath.segmentCount());
					if (diff.fNewPath != null)
						length= Math.min(length, diff.fNewPath.segmentCount());
					
					java.util.List hunks= diff.fHunks;
					java.util.Iterator iter= hunks.iterator();
					while (iter.hasNext()) {
						Hunk hunk= (Hunk) iter.next();
						TreeItem h= new TreeItem(d, SWT.NULL);
						h.setData(hunk);
						h.setText(hunk.getDescription());
					}
				}
			}
			if (fStripPrefixSegments != null && length != 99)
				for (int i= 1; i < length; i++)
					fStripPrefixSegments.add(Integer.toString(i));
		}
		
		updateTree();
	}
	
	private IFile existsInSelection(IPath path) {
		IResource target= fPatchWizard.getTarget();
		if (target instanceof IFile) {
			IFile file= (IFile) target;
			if (matches(file.getFullPath(), path))
				return file;
		} else if (target instanceof IContainer) {
			IContainer c= (IContainer) target;
			if (c.exists(path))
				return c.getFile(path);
		}
		return null;
	}
	
	/**
	 * Returns true if path completely matches the end of fullpath
	 */
	private boolean matches(IPath fullpath, IPath path) {
		
		for (IPath p= fullpath; path.segmentCount() <= p.segmentCount();
												p= p.removeFirstSegments(1)) {
			if (p.equals(path))
				return true;
		}
		return false;
	}
	
	/**
	 * Updates label and checked state of tree items.
	 */
	private void updateTree() {
		if (fTree == null || fTree.isDisposed())
			return;
		int strip= getStripPrefixSegments();
		TreeItem[] children= fTree.getItems();
		for (int i= 0; i < children.length; i++) {
			TreeItem item= children[i];
			Diff diff= (Diff) item.getData();
			diff.fMatches= false;
			String error= null;
			
			boolean create= false;	
			IFile file= null;
			if (diff.getType() == Differencer.ADDITION) {
				IPath p= diff.fNewPath;
				if (strip > 0 && strip < p.segmentCount())
					p= p.removeFirstSegments(strip);
				file= existsInSelection(p);
				if (file == null) {
					diff.fMatches= true;
				} else {
					// file already exists
					error= PatchMessages.getString("PreviewPatchPage.FileExists.error"); //$NON-NLS-1$
				}
				create= true;
			} else {
				IPath p= diff.fOldPath;
				if (strip > 0 && strip < p.segmentCount())
					p= p.removeFirstSegments(strip);
				file= existsInSelection(p);
				diff.fMatches= false;
				if (file != null) {
					if (file.isReadOnly()) {
						// file is readonly
						error= PatchMessages.getString("PreviewPatchPage.FileIsReadOnly.error"); //$NON-NLS-1$
						file= null;
					} else {
						diff.fMatches= true;
					}
				} else {
					// file doesn't exist
					error= PatchMessages.getString("PreviewPatchPage.FileDoesNotExist.error"); //$NON-NLS-1$
				}
			}
			
			ArrayList failedHunks= new ArrayList();
			fPatchWizard.getPatcher().apply(diff, file, create, failedHunks);

			if (failedHunks.size() > 0)
				diff.fRejected= fPatchWizard.getPatcher().getRejected(failedHunks);
			
			int checkedSubs= 0;	// counts checked hunk items
			TreeItem[] hunkItems= item.getItems();
			for (int h= 0; h < hunkItems.length; h++) {
				Hunk hunk= (Hunk) hunkItems[h].getData();
				boolean failed= failedHunks.contains(hunk);
				String hunkError= null;
				if (failed)
					hunkError= PatchMessages.getString("PreviewPatchPage.NoMatch.error"); //$NON-NLS-1$

				boolean check= !failed;
				hunkItems[h].setChecked(check);
				if (check)
					checkedSubs++;

				String hunkLabel= hunk.getDescription();
				if (hunkError != null)
					hunkLabel+= "   " + hunkError; //$NON-NLS-1$
				hunkItems[h].setText(hunkLabel);
				hunkItems[h].setImage(getImage(hunk));
			}
			
			String label= diff.getDescription(strip);
			if (error != null)
				label+= "    " + error; //$NON-NLS-1$
			item.setText(label);
			item.setImage(getImage(diff));
			item.setChecked(checkedSubs > 0);
			boolean gray= (checkedSubs > 0 &&  checkedSubs < hunkItems.length);
			item.setGrayed(gray);
			item.setExpanded(gray);
		}
		setPageComplete(updateModel());
	}
	
	/**
	 * Updates the gray state of the given diff and the checked state of its children.
	 */
	private void updateCheckedState(TreeItem diffItem) {
		boolean checked= diffItem.getChecked();
		// check whether we can enable all hunks
		TreeItem[] hunks= diffItem.getItems();
		int checkedCount= 0;
		for (int i= 0; i < hunks.length; i++) {
			Hunk hunk= (Hunk) hunks[i].getData();
			if (checked) {
				if (hunk.fMatches) {
					hunks[i].setChecked(true);
					checkedCount++;
				}
			} else {
				hunks[i].setChecked(false);
			}
		}
		diffItem.setGrayed(checkedCount > 0 && checkedCount < hunks.length);
		diffItem.setChecked(checkedCount > 0);
		
		setPageComplete(updateModel());
	}
	
	/**
	 * Updates the gray state of the given items parent.
	 */
	private void updateGrayedState(TreeItem hunk) {
		TreeItem diff= hunk.getParentItem();
		TreeItem[] hunks= diff.getItems();
		int checked= 0;
		for (int i= 0; i < hunks.length; i++)
			if (hunks[i].getChecked())
				checked++;
		diff.setChecked(checked > 0);
		diff.setGrayed(checked > 0 && checked < hunks.length);
		
		setPageComplete(updateModel());
	}
	
	private void addSpacer(Composite parent) {
		Label label= new Label(parent, SWT.NONE);
		GridData gd= new GridData(GridData.FILL_HORIZONTAL);
		gd.widthHint= 20;
		label.setLayoutData(gd);
	}
	
	private int getStripPrefixSegments() {
		int stripPrefixSegments= 0;
		if (fStripPrefixSegments != null) {
			String s= fStripPrefixSegments.getText();
			try {
				stripPrefixSegments= Integer.parseInt(s);
			} catch(NumberFormatException ex) {
			}
		}
		return stripPrefixSegments;
	}
	
	private int getFuzzFactor() {
		int fuzzFactor= 0;
		if (fFuzzField != null) {
			String s= fFuzzField.getText();
			try {
				fuzzFactor= Integer.parseInt(s);
			} catch(NumberFormatException ex) {
			}
		}
		return fuzzFactor;
	}
	
	public boolean updateModel() {
		boolean atLeastOneIsEnabled= false;
		if (fTree != null && !fTree.isDisposed()) {
			TreeItem [] diffItems= fTree.getItems();
			for (int i= 0; i < diffItems.length; i++) {
				TreeItem diffItem= diffItems[i];
				Object data= diffItem.getData();
				if (data instanceof Diff) {
					Diff diff= (Diff) data;
					boolean b= diffItem.getChecked();
					diff.setEnabled(b);
					if (b) {
						TreeItem [] hunkItems= diffItem.getItems();
						for (int j= 0; j < hunkItems.length; j++) {
							TreeItem hunkItem= hunkItems[j];
							data= hunkItem.getData();
							if (data instanceof Hunk) {
								Hunk hunk= (Hunk) data;
								b= hunkItem.getChecked();
								hunk.setEnabled(b);
								if (b) {
									atLeastOneIsEnabled= true;
								}
							}
						}
					}
				}
			}
		}
		return atLeastOneIsEnabled;
	}
}
