/*
 * 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.
 */

/*
 * User: anna
 * Date: 15-Apr-2009
 */
package com.intellij.codeInspection.ex;

import com.intellij.codeHighlighting.HighlightDisplayLevel;
import com.intellij.codeInsight.daemon.impl.SeverityRegistrar;
import com.intellij.codeInspection.InspectionProfile;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.packageDependencies.DependencyValidationManager;
import com.intellij.profile.ProfileEx;
import com.intellij.profile.ProfileManager;
import com.intellij.profile.codeInspection.SeverityProvider;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.search.scope.packageSet.CustomScopesProviderEx;
import com.intellij.psi.search.scope.packageSet.NamedScope;
import com.intellij.psi.search.scope.packageSet.NamedScopesHolder;
import com.intellij.psi.search.scope.packageSet.PackageSet;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

public class ToolsImpl implements Tools {
  @NonNls private static final String ENABLED_BY_DEFAULT_ATTRIBUTE = "enabled_by_default";
  @NonNls private static final String ENABLED_ATTRIBUTE = "enabled";
  @NonNls private static final String LEVEL_ATTRIBUTE = "level";

  private final String myShortName;
  private final ScopeToolState myDefaultState;
  private List<ScopeToolState> myTools;
  private boolean myEnabled;

  public ToolsImpl(@NotNull InspectionToolWrapper toolWrapper, @NotNull HighlightDisplayLevel level, boolean enabled, boolean enabledByDefault) {
    this(toolWrapper.getShortName(), new ScopeToolState(CustomScopesProviderEx.getAllScope(), toolWrapper, enabledByDefault, level), null, enabled);
  }

  @TestOnly
  public ToolsImpl(@NotNull InspectionToolWrapper toolWrapper, @NotNull HighlightDisplayLevel level, boolean enabled) {
    this(toolWrapper, level, enabled, enabled);
  }

  private ToolsImpl(@NotNull String shortName, @NotNull ScopeToolState defaultState, @Nullable List<ScopeToolState> tools, boolean enabled) {
    myShortName = shortName;
    myDefaultState = defaultState;
    myTools = tools;
    myEnabled = enabled;
  }

  @NotNull
  public ScopeToolState addTool(@NotNull NamedScope scope, @NotNull InspectionToolWrapper toolWrapper, boolean enabled, @NotNull HighlightDisplayLevel level) {
    return insertTool(scope, toolWrapper, enabled, level, myTools != null ? myTools.size() : 0);
  }

  @NotNull
  public ScopeToolState prependTool(@NotNull NamedScope scope, @NotNull InspectionToolWrapper toolWrapper, boolean enabled, @NotNull HighlightDisplayLevel level) {
    return insertTool(scope, toolWrapper, enabled, level, 0);
  }

  public ScopeToolState addTool(@NotNull String scopeName, @NotNull InspectionToolWrapper toolWrapper, boolean enabled, @NotNull HighlightDisplayLevel level) {
    return insertTool(new ScopeToolState(scopeName, toolWrapper, enabled, level), myTools != null ? myTools.size() : 0);
  }

  @NotNull
  private ScopeToolState insertTool(@NotNull NamedScope scope, @NotNull InspectionToolWrapper toolWrapper, boolean enabled, @NotNull HighlightDisplayLevel level, int idx) {
    return insertTool(new ScopeToolState(scope, toolWrapper, enabled, level), idx);
  }

  @NotNull
  private ScopeToolState insertTool(@NotNull final ScopeToolState scopeToolState, final int idx) {
    if (myTools == null) {
      myTools = new ArrayList<ScopeToolState>();
      if (scopeToolState.isEnabled()) {
        setEnabled(true);
      }
    }
    myTools.add(idx, scopeToolState);
    return scopeToolState;
  }

  @NotNull
  @Override
  public InspectionToolWrapper getInspectionTool(PsiElement element) {
    if (myTools != null) {
      final Project project = element != null ? element.getProject() : null;
      for (ScopeToolState state : myTools) {
        if (element == null) {
          return state.getTool();
        }
        else {
          final NamedScope scope = state.getScope(project);
          if (scope != null) {
            final PackageSet packageSet = scope.getValue();
            if (packageSet != null) {
              final PsiFile containingFile = element.getContainingFile();
              if (containingFile != null && packageSet.contains(containingFile, DependencyValidationManager.getInstance(project))) {
                return state.getTool();
              }
            }
          }
        }
      }

    }
    return myDefaultState.getTool();
  }

  @NotNull
  @Override
  public String getShortName() {
    return myShortName;
  }

  @NotNull
  public List<InspectionToolWrapper> getAllTools() {
    List<InspectionToolWrapper> result = new ArrayList<InspectionToolWrapper>();
    for (ScopeToolState state : getTools()) {
      InspectionToolWrapper toolWrapper = state.getTool();
      result.add(toolWrapper);
    }
    return result;
  }

  public void writeExternal(Element inspectionElement) throws WriteExternalException {
    if (myTools != null) {
      for (ScopeToolState state : myTools) {
        final Element scopeElement = new Element("scope");
        scopeElement.setAttribute("name", state.getScopeName());
        scopeElement.setAttribute(LEVEL_ATTRIBUTE, state.getLevel().getName());
        scopeElement.setAttribute(ENABLED_ATTRIBUTE, Boolean.toString(state.isEnabled()));
        InspectionToolWrapper toolWrapper = state.getTool();
        if (toolWrapper.isInitialized()) {
          toolWrapper.getTool().writeSettings(scopeElement);
        }
        inspectionElement.addContent(scopeElement);
      }
    }
    inspectionElement.setAttribute(ENABLED_ATTRIBUTE, Boolean.toString(isEnabled()));
    inspectionElement.setAttribute(LEVEL_ATTRIBUTE, getLevel().getName());
    inspectionElement.setAttribute(ENABLED_BY_DEFAULT_ATTRIBUTE, Boolean.toString(myDefaultState.isEnabled()));
    InspectionToolWrapper toolWrapper = myDefaultState.getTool();
    if (toolWrapper.isInitialized()) {
      toolWrapper.getTool().writeSettings(inspectionElement);
    }
  }

  void readExternal(@NotNull Element toolElement, @NotNull InspectionProfile profile, Map<String, List<String>> dependencies) throws InvalidDataException {
    final String levelName = toolElement.getAttributeValue(LEVEL_ATTRIBUTE);
    final ProfileManager profileManager = profile.getProfileManager();
    final SeverityRegistrar registrar = ((SeverityProvider)profileManager).getOwnSeverityRegistrar();
    HighlightDisplayLevel level = levelName != null ? HighlightDisplayLevel.find(registrar.getSeverity(levelName)) : null;
    if (level == null || level == HighlightDisplayLevel.DO_NOT_SHOW) {//from old profiles
      level = HighlightDisplayLevel.WARNING;
    }
    myDefaultState.setLevel(level);
    final String enabled = toolElement.getAttributeValue(ENABLED_ATTRIBUTE);
    final boolean isEnabled = enabled != null && Boolean.parseBoolean(enabled);

    final String enabledTool = toolElement.getAttributeValue(ENABLED_BY_DEFAULT_ATTRIBUTE);
    myDefaultState.setEnabled(enabledTool != null ? Boolean.parseBoolean(enabledTool) : isEnabled);
    final InspectionToolWrapper toolWrapper = myDefaultState.getTool();

    final List scopeElements = toolElement.getChildren(ProfileEx.SCOPE);
    final List<String> scopeNames = new ArrayList<String>();
    for (Object sO : scopeElements) {
      final Element scopeElement = (Element)sO;
      final String scopeName = scopeElement.getAttributeValue(ProfileEx.NAME);
      if (scopeName == null) {
        continue;
      }
      final NamedScopesHolder scopesHolder = profileManager.getScopesManager();
      NamedScope namedScope = null;
      if (scopesHolder != null) {
        namedScope = scopesHolder.getScope(scopeName);
      }
      final String errorLevel = scopeElement.getAttributeValue(LEVEL_ATTRIBUTE);
      final String enabledInScope = scopeElement.getAttributeValue(ENABLED_ATTRIBUTE);
      final InspectionToolWrapper copyToolWrapper = toolWrapper.createCopy();
    // check if unknown children exists
      if (scopeElement.getAttributes().size() > 3 || !scopeElement.getChildren().isEmpty()) {
        copyToolWrapper.getTool().readSettings(scopeElement);
      }
      HighlightDisplayLevel scopeLevel = errorLevel != null ?
                                         HighlightDisplayLevel.find(registrar.getSeverity(errorLevel)) : null;
      if (scopeLevel == null) {
        scopeLevel = level;
      }
      if (namedScope != null) {
        addTool(namedScope, copyToolWrapper, enabledInScope != null && Boolean.parseBoolean(enabledInScope), scopeLevel);
      }
      else {
        addTool(scopeName, copyToolWrapper, enabledInScope != null && Boolean.parseBoolean(enabledInScope), scopeLevel);
      }

      scopeNames.add(scopeName);
    }

    for (int i = 0; i < scopeNames.size(); i++) {
      String scopeName = scopeNames.get(i);
      List<String> order = dependencies.get(scopeName);
      if (order == null) {
        order = new ArrayList<String>();
        dependencies.put(scopeName, order);
      }
      for (int j = i + 1; j < scopeNames.size(); j++) {
        order.add(scopeNames.get(j));
      }
    }

    // check if unknown children exists
    if (toolElement.getAttributes().size() > 4 || toolElement.getChildren().size() > scopeElements.size()) {
      toolWrapper.getTool().readSettings(toolElement);
    }

    myEnabled = isEnabled;
  }

  @NotNull
  @Override
  public InspectionToolWrapper getTool() {
    if (myTools == null) return myDefaultState.getTool();
    return myTools.iterator().next().getTool();
  }

  @Override
  @NotNull
  public List<ScopeToolState> getTools() {
    if (myTools == null) return Collections.singletonList(myDefaultState);
    List<ScopeToolState> result = new ArrayList<ScopeToolState>(myTools);
    result.add(myDefaultState);
    return result;
  }

  @Override
  @NotNull
  public ScopeToolState getDefaultState() {
    return myDefaultState;
  }

  public void removeScope(int scopeIdx) {
    if (myTools != null && scopeIdx >= 0 && myTools.size() > scopeIdx) {
      myTools.remove(scopeIdx);
      checkToolsIsEmpty();
    }
  }

  public void removeScope(final @NotNull String scopeName) {
    if (myTools != null) {
      for (ScopeToolState tool : myTools) {
        if (scopeName.equals(tool.getScopeName())) {
          myTools.remove(tool);
          break;
        }
      }
      checkToolsIsEmpty();
    }
  }

  private void checkToolsIsEmpty() {
    if (myTools.isEmpty()) {
      myTools = null;
      setEnabled(myDefaultState.isEnabled());
    }
  }

  public void removeAllScopes() {
    myTools = null;
  }

  public void setScope(int idx, NamedScope namedScope) {
    if (myTools != null && myTools.size() > idx && idx >= 0) {
      final ScopeToolState scopeToolState = myTools.get(idx);
      InspectionToolWrapper toolWrapper = scopeToolState.getTool();
      myTools.remove(idx);
      myTools.add(idx, new ScopeToolState(namedScope, toolWrapper, scopeToolState.isEnabled(), scopeToolState.getLevel()));
    }
  }

  public void moveScope(int idx, int dir) {
    if (myTools != null && idx >= 0 && idx < myTools.size() && idx + dir >= 0 && idx + dir < myTools.size()) {
      final ScopeToolState state = myTools.get(idx);
      myTools.set(idx, myTools.get(idx + dir));
      myTools.set(idx + dir, state);
    }
  }

  public boolean isEnabled(NamedScope namedScope, Project project) {
    if (!myEnabled) return false;
    if (namedScope != null && myTools != null) {
      for (ScopeToolState state : myTools) {
        if (Comparing.equal(namedScope, state.getScope(project))) return state.isEnabled();
      }
    }
    return myDefaultState.isEnabled();
  }

  public HighlightDisplayLevel getLevel(PsiElement element) {
    if (myTools == null || element == null) return myDefaultState.getLevel();
    final Project project = element.getProject();
    final DependencyValidationManager manager = DependencyValidationManager.getInstance(project);
    for (ScopeToolState state : myTools) {
      final NamedScope scope = state.getScope(project);
      final PackageSet set = scope != null ? scope.getValue() : null;
      if (set != null && set.contains(element.getContainingFile(), manager)) {
        return state.getLevel();
      }
    }
    return myDefaultState.getLevel();
  }



  public HighlightDisplayLevel getLevel() {
    return myDefaultState.getLevel();
  }

  @Override
  public boolean isEnabled() {
    return myEnabled;
  }


  @Override
  public boolean isEnabled(PsiElement element) {
    if (!myEnabled) return false;
    if (myTools == null || element == null) return myDefaultState.isEnabled();
    final Project project = element.getProject();
    final DependencyValidationManager manager = DependencyValidationManager.getInstance(project);
    for (ScopeToolState state : myTools) {
      final NamedScope scope = state.getScope(project);
      if (scope != null) {
        final PackageSet set = scope.getValue();
        if (set != null && set.contains(element.getContainingFile(), manager)) {
          return state.isEnabled();
        }
      }
    }
    return myDefaultState.isEnabled();
  }

  @Override
  @Nullable
  public InspectionToolWrapper getEnabledTool(PsiElement element) {
    if (!myEnabled) return null;
    if (myTools == null || element == null) {
      return myDefaultState.isEnabled() ? myDefaultState.getTool() : null;
    }
    final Project project = element.getProject();
    final DependencyValidationManager manager = DependencyValidationManager.getInstance(project);
    for (ScopeToolState state : myTools) {
      final NamedScope scope = state.getScope(project);
      if (scope != null) {
        final PackageSet set = scope.getValue();
        if (set != null && set.contains(element.getContainingFile(), manager)) {
          return state.isEnabled() ? state.getTool() : null;
        }
      }
    }
    return myDefaultState.isEnabled() ? myDefaultState.getTool() : null;
  }

  public void setEnabled(boolean enabled) {
    myEnabled = enabled;
  }

  public void enableTool(NamedScope namedScope, Project project) {
    if (myTools != null) {
      for (ScopeToolState state : myTools) {
        if (Comparing.equal(state.getScope(project), namedScope)) {
          state.setEnabled(true);
        }
      }
    }
    setEnabled(true);
  }

  public void disableTool(NamedScope namedScope, Project project) {
    if (myTools != null) {
      for (ScopeToolState state : myTools) {
        if (Comparing.equal(state.getScope(project), namedScope)) {
          state.setEnabled(false);
        }
      }
    }
  }


  public void disableTool(@NotNull PsiElement element) {
    final Project project = element.getProject();
    final DependencyValidationManager validationManager = DependencyValidationManager.getInstance(project);
    if (myTools != null) {
      for (ScopeToolState state : myTools) {
        final NamedScope scope = state.getScope(project);
        if (scope != null) {
          final PackageSet packageSet = scope.getValue();
          if (packageSet != null && packageSet.contains(element.getContainingFile(), validationManager)) {
            state.setEnabled(false);
            return;
          }
        }
      }
      myDefaultState.setEnabled(false);
    }
    else {
      myDefaultState.setEnabled(false);
      setEnabled(false);
    }
  }

  @NotNull
  public HighlightDisplayLevel getLevel(final NamedScope scope, Project project) {
    if (myTools != null && scope != null){
      for (ScopeToolState state : myTools) {
        if (Comparing.equal(state.getScope(project), scope)) {
          return state.getLevel();
        }
      }
    }
    return myDefaultState.getLevel();
  }

   @Override
   public boolean equals(Object o) {
     ToolsImpl tools = (ToolsImpl)o;
      if (myEnabled != tools.myEnabled) return false;
      if (getTools().size() != tools.getTools().size()) return false;
      for (int i = 0; i < getTools().size(); i++) {
        final ScopeToolState state = getTools().get(i);
        final ScopeToolState toolState = tools.getTools().get(i);
        if (!state.equalTo(toolState)){
          return false;
        }
      }
      return true;

  }

  public void setLevel(@NotNull HighlightDisplayLevel level, @Nullable String scopeName, Project project) {
    if (scopeName == null) {
      myDefaultState.setLevel(level);
    } else {
      if (myTools == null) {
        return;
      }
      ScopeToolState scopeToolState = null;
      int index = -1;
      for (int i = 0; i < myTools.size(); i++) {
        ScopeToolState tool = myTools.get(i);
        if (scopeName.equals(tool.getScopeName())) {
          scopeToolState = tool;
          myTools.remove(tool);
          index = i;
          break;
        }
      }
      if (index < 0) {
        throw new IllegalStateException("Scope " + scopeName + " not found");
      }
      final InspectionToolWrapper toolWrapper = scopeToolState.getTool();
      final NamedScope scope = scopeToolState.getScope(project);
      if (scope != null) {
        myTools.add(index, new ScopeToolState(scope, toolWrapper, scopeToolState.isEnabled(), level));
      }
      else {
        myTools.add(index, new ScopeToolState(scopeToolState.getScopeName(), toolWrapper, scopeToolState.isEnabled(), level));
      }
    }
  }

  public void setDefaultState(@NotNull InspectionToolWrapper toolWrapper, boolean enabled, @NotNull HighlightDisplayLevel level) {
    myDefaultState.setTool(toolWrapper);
    myDefaultState.setLevel(level);
    myDefaultState.setEnabled(enabled);
  }

  public void setLevel(@NotNull HighlightDisplayLevel level) {
    myDefaultState.setLevel(level);
  }

  @Nullable
  public List<ScopeToolState> getNonDefaultTools() {
    return myTools;
  }
}