/*
 * Copyright 2000-2012 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.
 */

/*
 * Created by IntelliJ IDEA.
 * User: Anna.Kozlova
 * Date: 31-Jul-2006
 * Time: 17:44:39
 */
package com.intellij.profile.codeInspection.ui;

import com.intellij.codeHighlighting.HighlightDisplayLevel;
import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
import com.intellij.codeInsight.daemon.impl.SeverityRegistrar;
import com.intellij.codeInspection.InspectionManager;
import com.intellij.codeInspection.InspectionProfileEntry;
import com.intellij.codeInspection.ModifiableModel;
import com.intellij.codeInspection.ex.*;
import com.intellij.icons.AllIcons;
import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.colors.CodeInsightColors;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.fileChooser.FileChooser;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.options.BaseConfigurable;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.SearchableConfigurable;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.profile.Profile;
import com.intellij.profile.ProfileManager;
import com.intellij.profile.codeInspection.InspectionProfileManager;
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
import com.intellij.ui.ListCellRendererWrapper;
import com.intellij.ui.components.JBScrollPane;
import com.intellij.util.Alarm;
import com.intellij.util.Consumer;
import com.intellij.util.SystemProperties;
import com.intellij.util.containers.HashMap;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jetbrains.annotations.NotNull;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.List;

public abstract class InspectionToolsConfigurable extends BaseConfigurable implements ErrorsConfigurable, SearchableConfigurable,
                                                                                      Configurable.NoScroll {
  private final CardLayout myLayout = new CardLayout();
  private JPanel myPanel;

  public static final String ID = "Errors";
  public static final String DISPLAY_NAME = "Inspections";

  protected JComboBox myProfiles;
  private final Map<String, SingleInspectionProfilePanel> myPanels = new HashMap<String, SingleInspectionProfilePanel>();

  private JPanel myWholePanel;
  private JButton myAddButton;
  private JButton myDeleteButton;
  private JButton myImportButton;
  private JButton myExportButton;
  private JCheckBox myShareProfileCheckBox;
  private JButton myCopyButton;
  private JBScrollPane myJBScrollPane;

  private final List<String> myDeletedProfiles = new ArrayList<String>();
  protected final InspectionProfileManager myProfileManager;
  protected final InspectionProjectProfileManager myProjectProfileManager;
  private static final Logger LOG = Logger.getInstance("#" + InspectionToolsConfigurable.class.getName());
  private Alarm mySelectionAlarm;


  public InspectionToolsConfigurable(@NotNull final InspectionProjectProfileManager projectProfileManager, InspectionProfileManager profileManager) {
    ((InspectionManagerEx)InspectionManager.getInstance(projectProfileManager.getProject())).buildInspectionSearchIndexIfNecessary();
    myAddButton.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        final Set<String> existingProfileNames = myPanels.keySet();
        final ModifiableModel model = SingleInspectionProfilePanel.createNewProfile(-1, getSelectedObject(), myWholePanel, "", existingProfileNames,
                                                                                    projectProfileManager.getProject());
        if (model != null) {
          addProfile((InspectionProfileImpl)model);
          myDeletedProfiles.remove(getProfilePrefix(model) + model.getName());
          myDeleteButton.setEnabled(true);
        }
      }
    });

    myDeleteButton.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        final InspectionProfileImpl selectedProfile = (InspectionProfileImpl)myProfiles.getSelectedItem();
        ((DefaultComboBoxModel)myProfiles.getModel()).removeElement(selectedProfile);
        myDeletedProfiles.add(getProfilePrefix(selectedProfile) + selectedProfile.getName());
        myDeleteButton.setEnabled(isDeleteEnabled(selectedProfile));
      }
    });

    final Project project = projectProfileManager.getProject();
    myImportButton.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        final FileChooserDescriptor descriptor = new FileChooserDescriptor(true, false, false, false, false, false) {
          @Override
          public boolean isFileSelectable(VirtualFile file) {
            return file.getFileType().equals(StdFileTypes.XML);
          }
        };
        descriptor.setDescription("Choose profile file");
        FileChooser.chooseFile(descriptor, project, myWholePanel, null, new Consumer<VirtualFile>() {
          @Override
          public void consume(VirtualFile file) {
            if (file == null) return;
            InspectionProfileImpl profile =
              new InspectionProfileImpl("TempProfile", InspectionToolRegistrar.getInstance(), myProfileManager);
            try {
              Element rootElement = JDOMUtil.loadDocument(VfsUtilCore.virtualToIoFile(file)).getRootElement();
              if (Comparing.strEqual(rootElement.getName(), "component")) {//import right from .idea/inspectProfiles/xxx.xml
                rootElement = rootElement.getChildren().get(0);
              }
              final Set<String> levels = new HashSet<String>();
              for (Object o : rootElement.getChildren("inspection_tool")) {
                final Element inspectElement = (Element)o;
                levels.add(inspectElement.getAttributeValue("level"));
                for (Object s : inspectElement.getChildren("scope")) {
                  levels.add(((Element)s).getAttributeValue("level"));
                }
              }
              for (Iterator<String> iterator = levels.iterator(); iterator.hasNext(); ) {
                String level = iterator.next();
                if (myProfileManager.getOwnSeverityRegistrar().getSeverity(level) != null) {
                  iterator.remove();
                }
              }
              if (!levels.isEmpty()) {
                if (Messages.showYesNoDialog(myWholePanel, "Undefined severities detected: " +
                                                           StringUtil.join(levels, ", ") +
                                                           ". Do you want to create them?", "Warning", Messages.getWarningIcon()) ==
                    Messages.YES) {
                  for (String level : levels) {
                    final TextAttributes textAttributes = CodeInsightColors.WARNINGS_ATTRIBUTES.getDefaultAttributes();
                    HighlightInfoType.HighlightInfoTypeImpl info
                      = new HighlightInfoType.HighlightInfoTypeImpl(new HighlightSeverity(level, 50), com.intellij.openapi.editor.colors
                      .TextAttributesKey.createTextAttributesKey(level));
                    myProfileManager.getOwnSeverityRegistrar()
                      .registerSeverity(new SeverityRegistrar.SeverityBasedTextAttributes(textAttributes.clone(), info),
                                        textAttributes.getErrorStripeColor());
                  }
                }
              }
              profile.readExternal(rootElement);
              profile.setLocal(true);
              profile.initInspectionTools(project);
              if (getProfilePanel(profile) != null) {
                if (Messages.showOkCancelDialog(myWholePanel, "Profile with name \'" +
                                                              profile.getName() +
                                                              "\' already exists. Do you want to overwrite it?", "Warning",
                                                Messages.getInformationIcon()) != Messages.OK) return;
              }
              final ModifiableModel model = profile.getModifiableModel();
              model.setModified(true);
              addProfile((InspectionProfileImpl)model);
              myDeletedProfiles.remove(getProfilePrefix(profile) + profile.getName());
              myDeleteButton.setEnabled(true);
            }
            catch (InvalidDataException e1) {
              LOG.error(e1);
            }
            catch (JDOMException e1) {
              LOG.error(e1);
            }
            catch (IOException e1) {
              LOG.error(e1);
            }
          }
        });
      }
    });

    myExportButton.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        final FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor();
        descriptor.setDescription("Choose directory to store profile file");
        FileChooser.chooseFile(descriptor, project, myWholePanel, null, new Consumer<VirtualFile>() {
          @Override
          public void consume(VirtualFile file) {
            final Element element = new Element("inspections");
            try {
              final SingleInspectionProfilePanel panel = getSelectedPanel();
              LOG.assertTrue(panel != null);
              final InspectionProfileImpl profile = (InspectionProfileImpl)panel.getSelectedProfile();
              profile.writeExternal(element);
              final String filePath =
                FileUtil.toSystemDependentName(file.getPath()) + File.separator + FileUtil.sanitizeFileName(profile.getName()) + ".xml";
              if (new File(filePath).isFile()) {
                if (Messages
                      .showOkCancelDialog(myWholePanel, "File \'" + filePath + "\' already exist. Do you want to overwrite it?", "Warning",
                                          Messages.getQuestionIcon()) != Messages.OK) return;
              }
              JDOMUtil.writeDocument(new Document(element), filePath, SystemProperties.getLineSeparator());
            }
            catch (WriteExternalException e1) {
              LOG.error(e1);
            }
            catch (IOException e1) {
              LOG.error(e1);
            }
          }
        });

      }
    });

    myCopyButton.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        final Set<String> existingProfileNames = myPanels.keySet();
        final InspectionProfileImpl model = (InspectionProfileImpl)
          SingleInspectionProfilePanel.createNewProfile(0, getSelectedObject(), myWholePanel, "", existingProfileNames, project);
        if (model != null) {
          final InspectionProfileImpl modifiableModel = (InspectionProfileImpl)model.getModifiableModel();
          modifiableModel.setModified(true);
          addProfile(modifiableModel);
          myDeletedProfiles.remove(getProfilePrefix(model) + model.getName());
          myDeleteButton.setEnabled(true);
        }
      }
    });

    myProjectProfileManager = projectProfileManager;
    myProfileManager = profileManager;

    myJBScrollPane.setBorder(null);
  }

  private void addProfile(InspectionProfileImpl model) {
    final String modelName = model.getName();
    final SingleInspectionProfilePanel panel = createPanel(model, modelName, true);
    myPanel.add(modelName, panel);
    if (!myPanels.containsKey(getProfilePrefix(model) + modelName)) {
      //noinspection unchecked
      ((DefaultComboBoxModel)myProfiles.getModel()).addElement(model);
    }
    putProfile(model, panel);
    myProfiles.setSelectedItem(model);
  }

  @Override
  public String getDisplayName() {
    return DISPLAY_NAME;
  }

  @Override
  public String getHelpTopic() {
    return "preferences.inspections";
  }

  @Override
  @NotNull
  public String getId() {
    return ID;
  }

  @Override
  public Runnable enableSearch(final String option) {
    return new Runnable(){
      @Override
      public void run() {
        SingleInspectionProfilePanel panel = getSelectedPanel();
        if (panel != null) {
          panel.setFilter(option);
        }
      }
    };
  }

  @Override
  public JComponent createComponent() {
    myProfiles.setRenderer(new ListCellRendererWrapper<Profile>() {
      @Override
      public void customize(final JList list, final Profile value, final int index, final boolean selected, final boolean hasFocus) {
        final String profileName = value.getName();
        setText(profileName);
        final SingleInspectionProfilePanel panel = getProfilePanel(value);
        setIcon(panel != null && panel.isProfileShared() ? AllIcons.General.ProjectSettings : AllIcons.General.Settings);
      }
    });
    myProfiles.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        final InspectionProfileImpl profile = (InspectionProfileImpl)myProfiles.getSelectedItem();
        if (profile != null) {
          myDeleteButton.setEnabled(isDeleteEnabled(profile));
          myLayout.show(myPanel, profile.getName());
          SingleInspectionProfilePanel panel = getSelectedPanel();
          if (panel != null) {
            myShareProfileCheckBox.setSelected(panel.isProfileShared());
          }
        }
      }
    });
    myShareProfileCheckBox.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        final SingleInspectionProfilePanel panel = getSelectedPanel();
        LOG.assertTrue(panel != null, "No settings panel for: " + getSelectedObject());
        panel.setProfileShared(myShareProfileCheckBox.isSelected());
        myProfiles.repaint();
      }
    });

    myPanel.setLayout(myLayout);
    return myWholePanel;
  }

  protected abstract InspectionProfileImpl getCurrentProfile();

  @Override
  public boolean isModified() {
    for (SingleInspectionProfilePanel panel : myPanels.values()) {
      if (panel.isModified()) return true;
    }
    if (getProfiles().size() != myPanels.size()) return true;
    return !myDeletedProfiles.isEmpty();
  }

  @Override
  public void apply() throws ConfigurationException {
    final Map<String, SingleInspectionProfilePanel> panels = new LinkedHashMap<String, SingleInspectionProfilePanel>();
    for (final String name : myPanels.keySet()) {
      if (myDeletedProfiles.remove(name)) {
        final String profileName = getProfilePanel(name).getSelectedProfile().getName();
        deleteProfile(profileName);
      }
      else {
        final SingleInspectionProfilePanel panel = getProfilePanel(name);
        panel.apply();
        final ModifiableModel profile = panel.getSelectedProfile();
        panels.put(getProfilePrefix(profile) + profile.getName(), panel);
      }
    }
    myPanels.clear();
    myPanels.putAll(panels);
  }

  private SingleInspectionProfilePanel getProfilePanel(String name) {
    return myPanels.get(name);
  }

  private SingleInspectionProfilePanel getProfilePanel(Profile inspectionProfile) {
    return getProfilePanel(getProfilePrefix(inspectionProfile) + inspectionProfile.getName());
  }

  private void putProfile(Profile profile, SingleInspectionProfilePanel panel) {
    myPanels.put(getProfilePrefix(profile) + profile.getName(), panel);
  }

  private static String getProfilePrefix(Profile profile) {
    return (profile.isLocal() ? "L" : "S");
  }

  protected void deleteProfile(String name) {
    if (myProfileManager.getProfile(name, false) != null) {
      myProfileManager.deleteProfile(name);
    }
    if (myProjectProfileManager.getProfile(name, false) != null) {
      myProjectProfileManager.deleteProfile(name);
    }
  }

  protected boolean acceptTool(InspectionToolWrapper entry) {
    return true;
  }
  
  @Override
  public void reset() {
    myDeletedProfiles.clear();
    myPanels.clear();
    final DefaultComboBoxModel model = new DefaultComboBoxModel();
    myProfiles.setModel(model);
    for (Profile profile : getProfiles()) {
      model.addElement(profile);
      final String profileName = profile.getName();
      final SingleInspectionProfilePanel panel = createPanel((InspectionProfileImpl)profile, profileName, false);
      putProfile(profile, panel);
      myPanel.add(profileName, panel);
    }
    final InspectionProfileImpl inspectionProfile = getCurrentProfile();
    myProfiles.setSelectedItem(inspectionProfile);
    myLayout.show(myPanel, inspectionProfile.getName());
    myDeleteButton.setEnabled(isDeleteEnabled(inspectionProfile));
    final SingleInspectionProfilePanel panel = getSelectedPanel();
    if (panel != null) {
      panel.setVisible(true);//make sure that UI was initialized
      mySelectionAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD);
      SwingUtilities.invokeLater(new Runnable() {
        @Override
        public void run() {
          if (mySelectionAlarm != null) {
            mySelectionAlarm.addRequest(new Runnable() {
              @Override
              public void run() {
                panel.updateSelection();
              }
            }, 200);
          }
        }
      });

      myShareProfileCheckBox.setSelected(panel.isProfileShared());
    }
  }

  private SingleInspectionProfilePanel createPanel(InspectionProfileImpl profile, String profileName, boolean model) {
    return new SingleInspectionProfilePanel(myProjectProfileManager, profileName, model ? profile : profile.getModifiableModel()) {
      @Override
      protected boolean accept(InspectionToolWrapper entry) {
        return super.accept(entry) && InspectionToolsConfigurable.this.acceptTool(entry);
      }
    };
  }

  private boolean isDeleteEnabled(@NotNull InspectionProfileImpl inspectionProfile) {
    final ProfileManager profileManager = inspectionProfile.getProfileManager();

    boolean projectProfileFound = false;
    boolean ideProfileFound = false;

    final ComboBoxModel model = myProfiles.getModel();
    for (int i = 0; i < model.getSize(); i++) {
      Profile profile = (Profile)model.getElementAt(i);
      if (inspectionProfile == profile) continue;
      final boolean isProjectProfile = profile.getProfileManager() == myProjectProfileManager;
      projectProfileFound |= isProjectProfile;
      ideProfileFound |= !isProjectProfile;

      if (ideProfileFound && projectProfileFound) break;
    }

    return profileManager == myProjectProfileManager ? projectProfileFound : ideProfileFound;
  }

  protected Collection<Profile> getProfiles() {
    final Collection<Profile> result = new ArrayList<Profile>();
    result.addAll(new TreeSet<Profile>(myProfileManager.getProfiles()));
    result.addAll(myProjectProfileManager.getProfiles());
    return result;
  }

  @Override
  public void disposeUIResources() {
    for (SingleInspectionProfilePanel panel : myPanels.values()) {
      panel.disposeUI();
    }
    myPanels.clear();
    if (mySelectionAlarm != null) {
      Disposer.dispose(mySelectionAlarm);
      mySelectionAlarm = null;
    }
  }

  @Override
  public void selectProfile(String name) {
    for (int i = 0; i < myProfiles.getItemCount(); i++) {
      if (Comparing.strEqual(((InspectionProfileImpl)myProfiles.getItemAt(i)).getName(), name)) {
        myProfiles.setSelectedIndex(i);
        break;
      }
    }
  }

  @Override
  public void selectInspectionTool(String selectedToolShortName) {
    final InspectionProfileImpl inspectionProfile = getSelectedObject();
    assert inspectionProfile != null : configuredProfiles();
    final SingleInspectionProfilePanel panel = getProfilePanel(inspectionProfile);
    LOG.assertTrue(panel != null, "No settings panel for: " + inspectionProfile  + "; " + configuredProfiles());
    panel.selectInspectionTool(selectedToolShortName);
  }

  protected SingleInspectionProfilePanel getSelectedPanel() {
    final InspectionProfileImpl inspectionProfile = getSelectedObject();
    assert inspectionProfile != null : configuredProfiles();
    return getProfilePanel(inspectionProfile);
  }

  private String configuredProfiles() {
    return "configured profiles: " + StringUtil.join(myPanels.keySet(), ", ");
  }

  protected Set<String> getKnownNames() {
    return myPanels.keySet();
  }

  @Override
  public InspectionProfileImpl getSelectedObject() {
    return (InspectionProfileImpl)myProfiles.getSelectedItem();
  }

  @Override
  public JComponent getPreferredFocusedComponent() {
    final InspectionProfileImpl inspectionProfile = getSelectedObject();
    assert inspectionProfile != null : configuredProfiles();
    return getProfilePanel(inspectionProfile).getPreferredFocusedComponent();
  }
}
