/*
 * Copyright 2000-2014 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 org.jetbrains.java.debugger.breakpoints;

import com.intellij.debugger.InstanceFilter;
import com.intellij.debugger.ui.breakpoints.EditClassFiltersDialog;
import com.intellij.debugger.ui.breakpoints.EditInstanceFiltersDialog;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiClass;
import com.intellij.ui.FieldPanel;
import com.intellij.ui.MultiLineTooltipUI;
import com.intellij.ui.classFilter.ClassFilter;
import com.intellij.xdebugger.XSourcePosition;
import com.intellij.xdebugger.breakpoints.XBreakpoint;
import com.intellij.xdebugger.breakpoints.ui.XBreakpointCustomPropertiesPanel;
import com.intellij.xdebugger.impl.breakpoints.XBreakpointBase;
import com.intellij.xdebugger.impl.ui.DebuggerUIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.java.debugger.breakpoints.properties.JavaBreakpointProperties;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * @author egor
 */
public class JavaBreakpointFiltersPanel<T extends JavaBreakpointProperties, B extends XBreakpoint<T>> extends XBreakpointCustomPropertiesPanel<B> {
  private JPanel myConditionsPanel;
  private JPanel myInstanceFiltersPanel;
  private JCheckBox myInstanceFiltersCheckBox;
  private JPanel myInstanceFiltersFieldPanel;
  private JPanel myClassFiltersPanel;
  private JCheckBox myClassFiltersCheckBox;
  private JPanel myClassFiltersFieldPanel;
  private JPanel myPassCountPanel;
  private JCheckBox myPassCountCheckbox;
  private JTextField myPassCountField;

  private final FieldPanel myInstanceFiltersField;
  private final FieldPanel myClassFiltersField;

  private ClassFilter[] myClassFilters = ClassFilter.EMPTY_ARRAY;
  private ClassFilter[] myClassExclusionFilters = ClassFilter.EMPTY_ARRAY;
  private InstanceFilter[] myInstanceFilters = InstanceFilter.EMPTY_ARRAY;
  protected final Project myProject;

  private PsiClass myBreakpointPsiClass;

  public JavaBreakpointFiltersPanel(Project project) {
    myProject = project;
    myInstanceFiltersField = new FieldPanel(new MyTextField(), "", null,
                                            new ActionListener() {
                                              @Override
                                              public void actionPerformed(ActionEvent e) {
                                                reloadInstanceFilters();
                                                EditInstanceFiltersDialog _dialog = new EditInstanceFiltersDialog(myProject);
                                                _dialog.setFilters(myInstanceFilters);
                                                _dialog.show();
                                                if (_dialog.getExitCode() == DialogWrapper.OK_EXIT_CODE) {
                                                  myInstanceFilters = _dialog.getFilters();
                                                  updateInstanceFilterEditor(true);
                                                }
                                              }
                                            },
                                            null
    );

    myClassFiltersField = new FieldPanel(new MyTextField(), "", null,
                                         new ActionListener() {
                                           @Override
                                           public void actionPerformed(ActionEvent e) {
                                             reloadClassFilters();

                                             com.intellij.ide.util.ClassFilter classFilter = createClassConditionFilter();

                                             EditClassFiltersDialog _dialog = new EditClassFiltersDialog(myProject, classFilter);
                                             _dialog.setFilters(myClassFilters, myClassExclusionFilters);
                                             _dialog.show();
                                             if (_dialog.getExitCode() == DialogWrapper.OK_EXIT_CODE) {
                                               myClassFilters = _dialog.getFilters();
                                               myClassExclusionFilters = _dialog.getExclusionFilters();
                                               updateClassFilterEditor(true);
                                             }
                                           }
                                         },
                                         null
    );

    ActionListener updateListener = new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        updateCheckboxes();
      }
    };

    myPassCountCheckbox.addActionListener(updateListener);
    myInstanceFiltersCheckBox.addActionListener(updateListener);
    myClassFiltersCheckBox.addActionListener(updateListener);

    ToolTipManager.sharedInstance().registerComponent(myClassFiltersField.getTextField());
    ToolTipManager.sharedInstance().registerComponent(myInstanceFiltersField.getTextField());

    insert(myInstanceFiltersFieldPanel, myInstanceFiltersField);
    insert(myClassFiltersFieldPanel, myClassFiltersField);

    DebuggerUIUtil.focusEditorOnCheck(myPassCountCheckbox, myPassCountField);
    DebuggerUIUtil.focusEditorOnCheck(myInstanceFiltersCheckBox, myInstanceFiltersField.getTextField());
    DebuggerUIUtil.focusEditorOnCheck(myClassFiltersCheckBox, myClassFiltersField.getTextField());
  }

  @NotNull
  @Override
  public JComponent getComponent() {
    return myConditionsPanel;
  }

  @Override
  public boolean isVisibleOnPopup(@NotNull B breakpoint) {
    JavaBreakpointProperties properties = breakpoint.getProperties();
    if (properties != null) {
      return properties.isCOUNT_FILTER_ENABLED() || properties.isCLASS_FILTERS_ENABLED() || properties.isINSTANCE_FILTERS_ENABLED();
    }
    return false;
  }

  @Override
  public void saveTo(@NotNull B breakpoint) {
    JavaBreakpointProperties properties = breakpoint.getProperties();
    if (properties == null) {
      return;
    }

    boolean changed = false;
    try {
      String text = myPassCountField.getText().trim();
      int filter = !text.isEmpty() ? Integer.parseInt(text) : 0;
      if (filter < 0) filter = 0;
      changed = properties.setCOUNT_FILTER(filter);
    }
    catch (Exception ignored) {
    }

    changed = properties.setCOUNT_FILTER_ENABLED(properties.getCOUNT_FILTER() > 0 && myPassCountCheckbox.isSelected()) || changed;
    reloadInstanceFilters();
    reloadClassFilters();
    updateInstanceFilterEditor(true);
    updateClassFilterEditor(true);

    changed = properties.setINSTANCE_FILTERS_ENABLED(myInstanceFiltersField.getText().length() > 0 && myInstanceFiltersCheckBox.isSelected()) || changed;
    changed = properties.setCLASS_FILTERS_ENABLED(myClassFiltersField.getText().length() > 0 && myClassFiltersCheckBox.isSelected()) || changed;
    changed = properties.setClassFilters(myClassFilters) || changed;
    changed = properties.setClassExclusionFilters(myClassExclusionFilters) || changed;
    changed = properties.setInstanceFilters(myInstanceFilters) || changed;
    if (changed) {
      ((XBreakpointBase)breakpoint).fireBreakpointChanged();
    }
  }

  private static void insert(JPanel panel, JComponent component) {
    panel.setLayout(new BorderLayout());
    panel.add(component, BorderLayout.CENTER);
  }

  @Override
  public void loadFrom(@NotNull B breakpoint) {
    JavaBreakpointProperties properties = breakpoint.getProperties();
    if (properties != null) {
      if (properties.getCOUNT_FILTER() > 0) {
        myPassCountField.setText(Integer.toString(properties.getCOUNT_FILTER()));
      }
      else {
        myPassCountField.setText("");
      }

      myPassCountCheckbox.setSelected(properties.isCOUNT_FILTER_ENABLED());

      myInstanceFiltersCheckBox.setSelected(properties.isINSTANCE_FILTERS_ENABLED());
      myInstanceFiltersField.setEnabled(properties.isINSTANCE_FILTERS_ENABLED());
      myInstanceFiltersField.getTextField().setEditable(properties.isINSTANCE_FILTERS_ENABLED());
      myInstanceFilters = properties.getInstanceFilters();
      updateInstanceFilterEditor(true);

      myClassFiltersCheckBox.setSelected(properties.isCLASS_FILTERS_ENABLED());
      myClassFiltersField.setEnabled(properties.isCLASS_FILTERS_ENABLED());
      myClassFiltersField.getTextField().setEditable(properties.isCLASS_FILTERS_ENABLED());
      myClassFilters = properties.getClassFilters();
      myClassExclusionFilters = properties.getClassExclusionFilters();
      updateClassFilterEditor(true);

      XSourcePosition position = breakpoint.getSourcePosition();
      // TODO: need to calculate psi class
      //myBreakpointPsiClass = breakpoint.getPsiClass();
    }
    updateCheckboxes();
  }

  private void updateInstanceFilterEditor(boolean updateText) {
    List<String> filters = new ArrayList<String>();
    for (InstanceFilter instanceFilter : myInstanceFilters) {
      if (instanceFilter.isEnabled()) {
        filters.add(Long.toString(instanceFilter.getId()));
      }
    }
    if (updateText) {
      myInstanceFiltersField.setText(StringUtil.join(filters, " "));
    }

    String tipText = concatWithEx(filters, " ", (int)Math.sqrt(myInstanceFilters.length) + 1, "\n");
    myInstanceFiltersField.getTextField().setToolTipText(tipText);
  }

  private class MyTextField extends JTextField {
    public MyTextField() {
    }

    @Override
    public String getToolTipText(MouseEvent event) {
      reloadClassFilters();
      updateClassFilterEditor(false);
      reloadInstanceFilters();
      updateInstanceFilterEditor(false);
      String toolTipText = super.getToolTipText(event);
      return getToolTipText().length() == 0 ? null : toolTipText;
    }

    @Override
    public JToolTip createToolTip() {
      JToolTip toolTip = new JToolTip(){{
        setUI(new MultiLineTooltipUI());
      }};
      toolTip.setComponent(this);
      return toolTip;
    }
  }

  private void reloadClassFilters() {
    String filtersText = myClassFiltersField.getText();

    ArrayList<ClassFilter> classFilters     = new ArrayList<ClassFilter>();
    ArrayList<ClassFilter> exclusionFilters = new ArrayList<ClassFilter>();
    int startFilter = -1;
    for(int i = 0; i <= filtersText.length(); i++) {
      if(i < filtersText.length() && !Character.isWhitespace(filtersText.charAt(i))){
        if(startFilter == -1) {
          startFilter = i;
        }
      }
      else {
        if(startFilter >=0) {
          if(filtersText.charAt(startFilter) == '-') {
            exclusionFilters.add(new ClassFilter(filtersText.substring(startFilter + 1, i)));
          }
          else {
            classFilters.add(new ClassFilter(filtersText.substring(startFilter, i)));
          }
          startFilter = -1;
        }
      }
    }
    for (ClassFilter classFilter : myClassFilters) {
      if (!classFilter.isEnabled()) {
        classFilters.add(classFilter);
      }
    }
    for (ClassFilter classFilter : myClassExclusionFilters) {
      if (!classFilter.isEnabled()) {
        exclusionFilters.add(classFilter);
      }
    }
    myClassFilters          = classFilters    .toArray(new ClassFilter[classFilters    .size()]);
    myClassExclusionFilters = exclusionFilters.toArray(new ClassFilter[exclusionFilters.size()]);
  }

  private void reloadInstanceFilters() {
    String filtersText = myInstanceFiltersField.getText();

    ArrayList<InstanceFilter> idxs = new ArrayList<InstanceFilter>();
    int startNumber = -1;
    for(int i = 0; i <= filtersText.length(); i++) {
      if(i < filtersText.length() && Character.isDigit(filtersText.charAt(i))) {
        if(startNumber == -1) {
          startNumber = i;
        }
      }
      else {
        if(startNumber >=0) {
          idxs.add(InstanceFilter.create(filtersText.substring(startNumber, i)));
          startNumber = -1;
        }
      }
    }
    for (InstanceFilter instanceFilter : myInstanceFilters) {
      if (!instanceFilter.isEnabled()) {
        idxs.add(instanceFilter);
      }
    }
    myInstanceFilters = idxs.toArray(new InstanceFilter[idxs.size()]);
  }

  private void updateClassFilterEditor(boolean updateText) {
    List<String> filters = new ArrayList<String>();
    for (ClassFilter classFilter : myClassFilters) {
      if (classFilter.isEnabled()) {
        filters.add(classFilter.getPattern());
      }
    }
    List<String> excludeFilters = new ArrayList<String>();
    for (ClassFilter classFilter : myClassExclusionFilters) {
      if (classFilter.isEnabled()) {
        excludeFilters.add("-" + classFilter.getPattern());
      }
    }
    if (updateText) {
      String editorText = StringUtil.join(filters, " ");
      if(!filters.isEmpty()) {
        editorText += " ";
      }
      editorText += StringUtil.join(excludeFilters, " ");
      myClassFiltersField.setText(editorText);
    }

    int width = (int)Math.sqrt(myClassExclusionFilters.length + myClassFilters.length) + 1;
    String tipText = concatWithEx(filters, " ", width, "\n");
    if(!filters.isEmpty()) {
      tipText += "\n";
    }
    tipText += concatWithEx(excludeFilters, " ", width, "\n");
    myClassFiltersField.getTextField().setToolTipText(tipText);
  }

  private static String concatWithEx(List<String> s, String concator, int N, String NthConcator) {
    String result = "";
    int i = 1;
    for (Iterator iterator = s.iterator(); iterator.hasNext(); i++) {
      String str = (String) iterator.next();
      result += str;
      if(iterator.hasNext()){
        if(i % N == 0){
          result += NthConcator;
        }
        else {
          result += concator;
        }
      }
    }
    return result;
  }

  protected com.intellij.ide.util.ClassFilter createClassConditionFilter() {
    com.intellij.ide.util.ClassFilter classFilter;
    if(myBreakpointPsiClass != null) {
      classFilter = new com.intellij.ide.util.ClassFilter() {
        @Override
        public boolean isAccepted(PsiClass aClass) {
          return myBreakpointPsiClass == aClass || aClass.isInheritor(myBreakpointPsiClass, true);
        }
      };
    }
    else {
      classFilter = null;
    }
    return classFilter;
  }

  protected void updateCheckboxes() {
    boolean passCountApplicable = true;
    if (myInstanceFiltersCheckBox.isSelected() || myClassFiltersCheckBox.isSelected()) {
      passCountApplicable = false;
    }
    myPassCountCheckbox.setEnabled(passCountApplicable);

    final boolean passCountSelected = myPassCountCheckbox.isSelected();
    myInstanceFiltersCheckBox.setEnabled(!passCountSelected);
    myClassFiltersCheckBox.setEnabled(!passCountSelected);

    myPassCountField.setEditable(myPassCountCheckbox.isSelected());
    myPassCountField.setEnabled (myPassCountCheckbox.isSelected());

    myInstanceFiltersField.setEnabled(myInstanceFiltersCheckBox.isSelected());
    myInstanceFiltersField.getTextField().setEditable(myInstanceFiltersCheckBox.isSelected());

    myClassFiltersField.setEnabled(myClassFiltersCheckBox.isSelected());
    myClassFiltersField.getTextField().setEditable(myClassFiltersCheckBox.isSelected());
  }
}
