package osmedile.intellij.stringmanip;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.jetbrains.annotations.Nullable;

import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.editor.actionSystem.EditorAction;
import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.UserDataHolder;

public class RemoveDuplicateLinesAction extends EditorAction {

	private static final Key<Set<String>> KEY = Key.create("StringManipulation.RemoveDuplicateLines");

	public RemoveDuplicateLinesAction() {
		super(new EditorWriteActionHandler(true) {
			public void executeWriteAction(Editor editor, @Nullable Caret caret, DataContext dataContext) {

				// Column mode not supported
				if (editor.isColumnMode()) {
					return;
				}
				final SelectionModel selectionModel = editor.getSelectionModel();
				boolean hasSelection = selectionModel.hasSelection();
				if (!hasSelection) {
					return;
				}
				final String selectedText = selectionModel.getSelectedText();
				if (selectedText != null) {
					int selectionStart = selectionModel.getSelectionStart();
					int selectionEnd = selectionModel.getSelectionEnd();

					String[] split = selectedText.split("\n");
					String[] uniqueLines = filter(editor, split);
					naiveCleanup(editor, caret);

					String result = join(uniqueLines, selectedText.length());

					editor.getDocument().replaceString(selectionStart, selectionEnd, result);
					editor.getCaretModel().moveToOffset(selectionStart + result.length());
					selectionModel.setSelection(selectionStart, selectionStart + result.length());
				}
			}

			private String join(String[] array, int length) {
				StringBuilder buf = new StringBuilder(length);
				for (int i = 0; i < array.length; i++) {
					if (array[i] != null && i > 0) {
						buf.append("\n");
					}
					if (array[i] != null) {
						buf.append(array[i]);
					}
				}
				return buf.toString();
			}

			private String[] filter(UserDataHolder dataContext, String[] split) {
				if (split.length > 0) {
					Set<String> set = KEY.get(dataContext);
					if (set == null) {
						set = new HashSet<String>();
						dataContext.putUserData(KEY, set);
					}
					for (int i = 0; i < split.length; i++) {
						boolean unique = set.add(split[i]);
						if (!unique) {
							split[i] = null;
						}
					}
					return split;
				}
				return split;
			}

			private void naiveCleanup(Editor editor, Caret caret) {
				List<Caret> allCarets = editor.getCaretModel().getAllCarets();
				if (allCarets.get(0) == caret) {
					editor.putUserData(KEY, null);
				}
			}
		});
	}
}
@@ -911,17 +911,16 @@
 text) %7B%0A
-%0A
 %09%09%09%09// C
@@ -988,32 +988,43 @@
 %09%09return;%0A%09%09%09%09%7D%0A
+%09%09%09%09try %7B%0A%09
 %09%09%09%09final Select
@@ -1073,24 +1073,25 @@
 ionModel();%0A
+%09
 %09%09%09%09boolean 
@@ -1136,24 +1136,25 @@
 tion();%0A%09%09%09%09
+%09
 if (!hasSele
@@ -1163,32 +1163,33 @@
 ion) %7B%0A%09%09%09%09%09
+%09
 return;%0A
 %09%09%09%09%7D%0A%09%09%09%09fi
@@ -1168,32 +1168,33 @@
 %7B%0A%09%09%09%09%09%09return;%0A
+%09
 %09%09%09%09%7D%0A%09%09%09%09final 
@@ -1183,24 +1183,25 @@
 %0A%09%09%09%09%09%7D%0A%09%09%09%09
+%09
 final String
@@ -1246,24 +1246,25 @@
 ctedText();%0A
+%09
 %09%09%09%09if (sele
@@ -1284,24 +1284,25 @@
 ull) %7B%0A%09%09%09%09%09
+%09
 int selectio
@@ -1342,24 +1342,25 @@
 ionStart();%0A
+%09
 %09%09%09%09%09int sel
@@ -1407,24 +1407,25 @@
 nd();%0A%0A%09%09%09%09%09
+%09
 String%5B%5D spl
@@ -1451,24 +1451,25 @@
 plit(%22%5Cn%22);%0A
+%09
 %09%09%09%09%09String%5B
@@ -1511,43 +1511,10 @@
 t);%0A
-%09%09%09%09%09naiveCleanup(editor, caret);%0A
 %0A
+%09
 %09%09%09%09
@@ -1569,24 +1569,25 @@
 length());%0A%0A
+%09
 %09%09%09%09%09editor.
@@ -1649,24 +1649,25 @@
 d, result);%0A
+%09
 %09%09%09%09%09editor.
@@ -1735,16 +1735,17 @@
 );%0A%09%09%09%09%09
+%09
 selectio
@@ -1811,24 +1811,81 @@
 .length());%0A
+%09%09%09%09%09%7D%0A%09%09%09%09%7D finally %7B%0A%09%09%09%09%09naiveCleanup(editor, caret);%0A
 %09%09%09%09%7D%0A%09%09%09%7D%0A%0A

Remove duplicate lines - better cleanup