/*
 * Copyright 2000-2011 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.intellij.ide.actions;

import com.intellij.codeInsight.CodeInsightUtilBase;
import com.intellij.codeInsight.editorActions.PasteHandler;
import com.intellij.ide.IdeBundle;
import com.intellij.ide.PasteProvider;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorModificationUtil;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.ide.CopyPasteManager;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.util.Producer;
import org.jetbrains.annotations.Nullable;

import java.awt.datatransfer.Transferable;

public class PasteReferenceProvider implements PasteProvider {
  public void performPaste(DataContext dataContext) {
    final Project project = PlatformDataKeys.PROJECT.getData(dataContext);
    final Editor editor = PlatformDataKeys.EDITOR.getData(dataContext);
    if (project == null || editor == null) return;

    final String fqn = getCopiedFqn(dataContext);

    QualifiedNameProvider theProvider = null;
    PsiElement element = null;
    for(QualifiedNameProvider provider: Extensions.getExtensions(QualifiedNameProvider.EP_NAME)) {
      element = provider.qualifiedNameToElement(fqn, project);
      if (element != null) {
        theProvider = provider;
        break;
      }
    }

    if (theProvider != null) {
      insert(fqn, element, editor, theProvider);
    }
  }

  public boolean isPastePossible(DataContext dataContext) {
    final Project project = PlatformDataKeys.PROJECT.getData(dataContext);
    final Editor editor = PlatformDataKeys.EDITOR.getData(dataContext);
    return project != null && editor != null && getCopiedFqn(dataContext) != null;
  }

  public boolean isPasteEnabled(DataContext dataContext) {
    final Project project = PlatformDataKeys.PROJECT.getData(dataContext);
    String fqn = getCopiedFqn(dataContext);
    if (project == null || fqn == null) {
      return false;
    }
    for(QualifiedNameProvider provider: Extensions.getExtensions(QualifiedNameProvider.EP_NAME)) {
      if (provider.qualifiedNameToElement(fqn, project) != null) {
        return true;
      }
    }
    return false;
  }

  private static void insert(final String fqn, final PsiElement element, final Editor editor, final QualifiedNameProvider provider) {
    final Project project = editor.getProject();
    if (project == null) return;

    final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project);
    documentManager.commitDocument(editor.getDocument());

    final PsiFile file = documentManager.getPsiFile(editor.getDocument());
    if (!CodeInsightUtilBase.prepareFileForWrite(file)) return;

    CommandProcessor.getInstance().executeCommand(project, new Runnable() {
      public void run() {
        ApplicationManager.getApplication().runWriteAction(new Runnable() {
          public void run() {
            Document document = editor.getDocument();
            documentManager.doPostponedOperationsAndUnblockDocument(document);
            documentManager.commitDocument(document);
            EditorModificationUtil.deleteSelectedText(editor);
            provider.insertQualifiedName(fqn, element, editor, project);
          }
        });
      }
    }, IdeBundle.message("command.pasting.reference"), null);
  }

  @Nullable
  private static String getCopiedFqn(DataContext dataContext) {
    Transferable transferable = null;

    @SuppressWarnings("unchecked")
    Producer<Transferable> transferableProducer = (Producer<Transferable>)dataContext.getData(PasteHandler.TRANSFERABLE_PROVIDER);
    if (transferableProducer != null) {
      transferable = transferableProducer.produce();
      if (transferable == null) {
        transferable = CopyPasteManager.getInstance().getContents();
      }
    }
    if (transferable == null) return null;

    try {
      return (String)transferable.getTransferData(CopyReferenceAction.ourFlavor);
    }
    catch (Exception ignored) { }

    return null;
  }
}

@@ -17,17 +17,17 @@
 2000-201
-1
+2
  JetBrai
@@ -4309,16 +4309,22 @@
 piedFqn(
+final 
 DataCont
@@ -4346,47 +4346,8 @@
 ) %7B%0A
-    Transferable transferable = null;%0A%0A
     
@@ -4381,16 +4381,22 @@
 d%22)%0A    
+final 
 Producer
@@ -4543,25 +4543,25 @@
 roducer 
-!
+=
 = null) 
 %7B%0A      
@@ -4552,23 +4552,52 @@
 = null) 
-%7B%0A     
+return null;%0A%0A    final Transferable
  transfe
@@ -4636,26 +4636,24 @@
 duce();%0A    
-  
 if (transfer
@@ -4649,33 +4649,33 @@
 f (transferable 
-=
+!
 = null) %7B%0A      
@@ -4678,139 +4678,397 @@
     
-  transferable = CopyPasteManager.getInstance().getContents();%0A      %7D%0A    %7D%0A    if (transferable == null) return null;%0A%0A
+try %7B%0A        return (String)transferable.getTransferData(CopyReferenceAction.ourFlavor);%0A      %7D%0A      catch (Exception ignored) %7B %7D%0A    %7D%0A%0A    final CopyPasteManager manager = CopyPasteManager.getInstance();%0A    if (manager.isDataFlavorAvailable(CopyReferenceAction.ourFlavor)) %7B%0A      final Transferable contents = manager.getContents();%0A      if (contents != null) %7B%0A   
     
+ 
 try %7B%0A
+    
     
@@ -5080,36 +5080,32 @@
 urn (String)
-transferable
+contents
 .getTransfer
@@ -5141,26 +5141,34 @@
 lavor);%0A    
-%7D%0A
+    %7D%0A    
     catch (E
@@ -5188,16 +5188,30 @@
 red) %7B %7D
+%0A      %7D%0A    %7D
 %0A%0A    re

Check clipboard before getting content