/*
 * Copyright 2000-2013 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.debugger.ui;

import com.intellij.debugger.engine.evaluation.*;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.event.DocumentAdapter;
import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.editor.event.DocumentListener;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.ui.EditorComboBoxEditor;
import com.intellij.ui.EditorComboBoxRenderer;
import com.intellij.ui.EditorTextField;
import com.intellij.xdebugger.XExpression;
import com.intellij.xdebugger.impl.XDebuggerHistoryManager;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import javax.swing.plaf.basic.ComboPopup;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @author ven
 */
public class DebuggerExpressionComboBox extends DebuggerEditorImpl {
  public static final Key<String> KEY = Key.create("DebuggerComboBoxEditor.KEY");
  public static final int MAX_ROWS = 20;

  private MyEditorComboBoxEditor myEditor;
  private ComboBox myComboBox;

  private class MyEditorComboBoxEditor extends EditorComboBoxEditor {

    public MyEditorComboBoxEditor(Project project, FileType fileType) {
      super(project, fileType);
    }

    public Object getItem() {
      Document document = (Document)super.getItem();
      return createItem(document, getProject());
    }

    public void setItem(Object item) {
      TextWithImports twi = (TextWithImports)item;
      if (twi != null) {
        restoreFactory(twi);
      }
      final Document document = createDocument(twi);
      getEditorComponent().setNewDocumentAndFileType(getCurrentFactory().getFileType(), document);
      super.setItem(document);

      // need to replace newlines with spaces, see IDEA-81789
      if (document != null) {
        document.addDocumentListener(REPLACE_NEWLINES_LISTENER);
      }
      /* Causes PSI being modified from PSI events. See IDEADEV-22102
      final Editor editor = getEditor();
      if (editor != null) {
        DaemonCodeAnalyzer.getInstance(getProject()).updateVisibleHighlighters(editor);
      }
      */
    }

  }

  private static DocumentListener REPLACE_NEWLINES_LISTENER = new DocumentAdapter() {
    @Override
    public void documentChanged(DocumentEvent e) {
      final String text = e.getNewFragment().toString();
      final String replaced = text.replace('\n', ' ');
      if (replaced != text) {
        e.getDocument().replaceString(e.getOffset(), e.getOffset() + e.getNewLength(), replaced);
      }
    }
  };

  public DebuggerExpressionComboBox(Project project, @NonNls String recentsId) {
    this(project, null, recentsId, DefaultCodeFragmentFactory.getInstance());
  }

  public DebuggerExpressionComboBox(Project project, PsiElement context, @NonNls String recentsId, final CodeFragmentFactory factory) {
    super(project, context, recentsId, factory);
    setLayout(new BorderLayout(0, 0));

    myComboBox = new ComboBox(new MyComboboxModel(getRecents()), 100);
    myComboBox.setSwingPopup(false);

    // Have to turn this off because when used in DebuggerTreeInplaceEditor, the combobox popup is hidden on every change of selection
    // See comment to SynthComboBoxUI.FocusHandler.focusLost()
    myComboBox.setLightWeightPopupEnabled(false);

    myEditor = new MyEditorComboBoxEditor(getProject(), getCurrentFactory().getFileType());
    //noinspection GtkPreferredJComboBoxRenderer
    myComboBox.setRenderer(new EditorComboBoxRenderer(myEditor));

    myComboBox.setEditable(true);
    myComboBox.setEditor(myEditor);
    add(addChooseFactoryLabel(myComboBox, false));
  }

  public void selectPopupValue() {
    //selectAll();
    final Object currentPopupValue = getCurrentPopupValue();
    if (currentPopupValue != null) {
      myComboBox.getModel().setSelectedItem(currentPopupValue);
      myComboBox.getEditor().setItem(currentPopupValue);
    }

    myComboBox.setPopupVisible(false);
  }

  public boolean isPopupVisible() {
    return myComboBox.isVisible() && myComboBox.isPopupVisible();
  }

  public void setPopupVisible(final boolean b) {
    myComboBox.setPopupVisible(b);
  }

  @Nullable
  public Object getCurrentPopupValue() {
    if (!isPopupVisible()) return null;

    final ComboPopup popup = myComboBox.getPopup();
    if (popup != null) {
      return popup.getList().getSelectedValue();
    }

    return null;
  }

  @Override
  protected void doSetText(TextWithImports item) {
    final String itemText = item.getText().replace('\n', ' ');
    restoreFactory(item);
    item.setText(itemText);
    if (!StringUtil.isEmpty(itemText)) {
      if (myComboBox.getItemCount() == 0 || !item.equals(myComboBox.getItemAt(0))) {
        myComboBox.insertItemAt(item, 0);
      }
    }
    if (myComboBox.getItemCount() > 0) {
      myComboBox.setSelectedIndex(0);
    }

    myComboBox.getEditor().setItem(item);
  }

  @Override
  protected void updateEditorUi() {
  }

  public TextWithImports getText() {
    return (TextWithImports)myComboBox.getEditor().getItem();
  }

  @Nullable
  private List<TextWithImports> getRecents() {
    final String recentsId = getRecentsId();
    if (recentsId != null) {
      final List<TextWithImports> result = new ArrayList<TextWithImports>();
      List<XExpression> recents = XDebuggerHistoryManager.getInstance(getProject()).getRecentExpressions(getRecentsId());
      for (XExpression expression : recents) {
        if (expression.getExpression().indexOf('\n') == -1) {
          result.add(TextWithImportsImpl.fromXExpression(expression));
        }
      }

      return result;
    }

    return null;
  }

  public Dimension getMinimumSize() {
    Dimension size = super.getMinimumSize();
    size.width = 100;
    return size;
  }

  public TextWithImports createText(String text, String importsString) {
    return new TextWithImportsImpl(CodeFragmentKind.EXPRESSION, text, importsString, getCurrentFactory().getFileType());
  }

  @Override
  public void setEnabled(boolean enabled) {
    super.setEnabled(enabled);
    myComboBox.setEnabled(enabled);
    //if (enabled) {
    //  final ComboBoxEditor editor = myComboBox.getEditor();
    //  editor.setItem(editor.getItem());
    //}
  }

  public JComponent getPreferredFocusedComponent() {
    return (JComponent)myComboBox.getEditor().getEditorComponent();
  }

  public void selectAll() {
    myComboBox.getEditor().selectAll();
  }

  public Editor getEditor() {
    return myEditor.getEditor();
  }

  public JComponent getEditorComponent() {
    return myEditor.getEditorComponent();
  }

  public void addRecent(TextWithImports text) {
    if (text.getText().length() != 0) {
      Component editorComponent = myComboBox.getEditor().getEditorComponent();
      final boolean focusOwner = editorComponent.isFocusOwner();
      int offset = -1;
      if (editorComponent instanceof EditorTextField) {
        final EditorTextField textField = (EditorTextField)editorComponent;
        if (textField.getEditor() != null) {
          offset = textField.getCaretModel().getOffset();
        }
      }
      super.addRecent(text);
      myComboBox.insertItemAt(text, 0);
      myComboBox.setSelectedIndex(0);
      editorComponent = myComboBox.getEditor().getEditorComponent();
      if (offset != -1 && editorComponent instanceof EditorTextField) {
        final EditorTextField textField = (EditorTextField)editorComponent;
        final Editor editor = textField.getEditor();
        if (editor != null) {
          int textLength = editor.getDocument().getTextLength();
          offset = Math.min(offset, textLength);
          textField.getCaretModel().moveToOffset(offset);
          editor.getSelectionModel().setSelection(offset, offset);
        }
      }

      if (focusOwner) {
        editorComponent.requestFocus();
      }
    }
  }

  private static class MyComboboxModel extends AbstractListModel implements MutableComboBoxModel {
    private List<TextWithImports> myItems = new ArrayList<TextWithImports>();
    private int mySelectedIndex = -1;

    private MyComboboxModel(@Nullable final List<TextWithImports> recents) {
      if (recents != null) {
        myItems = recents;
      }
    }

    @Override
    public void setSelectedItem(final Object anItem) {
      final int oldSelectedIndex = mySelectedIndex;
      mySelectedIndex = anItem instanceof TextWithImports ? myItems.indexOf(anItem) : -1;
      if (oldSelectedIndex != mySelectedIndex) fireContentsChanged(this, -1, -1);
    }

    @Override
    public Object getSelectedItem() {
      return mySelectedIndex == -1 || mySelectedIndex > myItems.size() - 1 ? null : myItems.get(mySelectedIndex);
    }

    @Override
    public int getSize() {
      return myItems.size();
    }

    @Override
    public Object getElementAt(int index) {
      return myItems.get(index);
    }

    @Override
    public void addElement(final Object obj) {
      insertElementAt(obj, myItems.size() - 1);

      if (mySelectedIndex == -1 && myItems.size() == 1 && obj != null) {
        setSelectedItem(obj);
      }
    }

    @Override
    public void removeElement(Object obj) {
      removeElement(obj, true);
    }

    public void removeElement(final Object obj, final boolean checkSelection) {
      if (!(obj instanceof TextWithImports)) throw new IllegalArgumentException();
      final int index = myItems.indexOf((TextWithImports)obj);
      if (index != -1) {
        myItems.remove(index);

        if (checkSelection) {
          if (mySelectedIndex == index) {
            if (myItems.size() == 0) {
              setSelectedItem(null);
            }
            else if (index > myItems.size() - 1) {
              setSelectedItem(myItems.get(myItems.size() - 1));
            }
          }

          fireIntervalRemoved(this, index, index);
        }
      }
    }

    @Override
    public void insertElementAt(final Object obj, final int index) {
      if (!(obj instanceof TextWithImports)) throw new IllegalArgumentException();
      removeElement(obj, false); // remove duplicate entry if any

      myItems.add(index, (TextWithImports)obj);
      fireIntervalAdded(this, index, index);

      if (myItems.size() > MAX_ROWS) {
        for (int i = myItems.size() - 1; i > MAX_ROWS - 1; i--) {
          myItems.remove(i);
        }

        // will not fire events here to not recreate the editor
        //fireIntervalRemoved(this, myItems.size() - 1, MAX_ROWS - 1);
      }
    }

    @Override
    public void removeElementAt(final int index) {
      if (index < 0 || index > myItems.size() - 1) throw new IndexOutOfBoundsException();
      removeElement(myItems.get(index));
    }
  }
}