/*
 * 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.
 */
package com.intellij.application.options.codeStyle.arrangement.match;

import com.intellij.application.options.codeStyle.arrangement.ArrangementConstants;
import com.intellij.application.options.codeStyle.arrangement.color.ArrangementColorsProvider;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.codeStyle.arrangement.ArrangementUtil;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryMatcher;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementMatchRule;
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementEntryMatcher;
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementMatchRule;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
import com.intellij.psi.codeStyle.arrangement.std.*;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.util.containers.ContainerUtilRt;
import com.intellij.util.ui.GridBag;
import com.intellij.util.ui.MultiRowFlowPanel;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.*;
import java.util.List;

/**
 * Control for managing {@link ArrangementEntryMatcher matching rule conditions} for a single {@link ArrangementMatchRule}.
 * <p/>
 * Not thread-safe.
 *
 * @author Denis Zhdanov
 * @since 8/14/12 9:54 AM
 */
public class ArrangementMatchingRuleEditor extends JPanel implements ArrangementUiComponent.Listener {

  @NotNull private final Map<ArrangementSettingsToken, ArrangementUiComponent> myComponents = ContainerUtilRt.newHashMap();
  @NotNull private final List<MultiRowFlowPanel>                               myRows       = ContainerUtilRt.newArrayList();

  @NotNull private final ArrangementMatchingRulesControl    myControl;
  @NotNull private final ArrangementStandardSettingsManager mySettingsManager;
  @NotNull private final ArrangementColorsProvider          myColorsProvider;

  private int myRow = -1;
  private int        myLabelWidth;
  
  @Nullable private JComponent myDefaultFocusRequestor;
  @Nullable private JComponent myFocusRequestor;
  
  private boolean mySkipStateChange;

  public ArrangementMatchingRuleEditor(@NotNull ArrangementStandardSettingsManager settingsManager,
                                       @NotNull ArrangementColorsProvider colorsProvider,
                                       @NotNull ArrangementMatchingRulesControl control)
  {
    this(settingsManager, settingsManager.getSupportedMatchingTokens(), colorsProvider, control);
  }

  public ArrangementMatchingRuleEditor(@NotNull ArrangementStandardSettingsManager settingsManager,
                                       @Nullable List<CompositeArrangementSettingsToken> tokens,
                                       @NotNull ArrangementColorsProvider colorsProvider,
                                       @NotNull ArrangementMatchingRulesControl control)
  {
    mySettingsManager = settingsManager;
    myColorsProvider = colorsProvider;
    myControl = control;
    init(tokens);
    addMouseListener(new MouseAdapter() {
      @Override
      public void mouseClicked(MouseEvent e) {
        onMouseClicked(e);
      }
    });
  }

  private void init(@Nullable List<CompositeArrangementSettingsToken> tokens) {
    setLayout(new GridBagLayout());
    setBorder(IdeBorderFactory.createEmptyBorder(5));

    if (tokens != null) {
      for (CompositeArrangementSettingsToken token : tokens) {
        addToken(token);
      }
    }

    applyBackground(UIUtil.getListBackground());
  }

  private void addToken(@NotNull CompositeArrangementSettingsToken rowToken) {
    List<CompositeArrangementSettingsToken> tokens = ArrangementUtil.flatten(rowToken);
    GridBag labelConstraints = new GridBag().anchor(GridBagConstraints.NORTHWEST).insets(ArrangementConstants.VERTICAL_PADDING, 0, 0, 0);
    MultiRowFlowPanel panel = new MultiRowFlowPanel(
      FlowLayout.LEFT, ArrangementConstants.HORIZONTAL_GAP, ArrangementConstants.VERTICAL_GAP
    );
    List<ArrangementSettingsToken> prevTokens = ContainerUtilRt.newArrayList();
    StdArrangementTokenUiRole prevRole = null;
    ArrangementUiComponent component;
    JComponent uiComponent;
    for (CompositeArrangementSettingsToken token : tokens) {
      StdArrangementTokenUiRole role = token.getRole();
      if (role != prevRole && !prevTokens.isEmpty()) {
        component = ArrangementUtil.buildUiComponent(
          role, prevTokens, myColorsProvider, mySettingsManager
        );
        component.setListener(this);
        for (ArrangementSettingsToken prevToken : prevTokens) {
          myComponents.put(prevToken, component);
        }
        panel.add(component.getUiComponent());
        panel = addRowIfNecessary(panel);
        prevRole = null;
        prevTokens.clear();
      }
      component = ArrangementUtil.buildUiComponent(
        role, Collections.singletonList(token.getToken()), myColorsProvider, mySettingsManager
      );
      component.setListener(this);
      uiComponent = component.getUiComponent();
      switch (role) {
        case LABEL:
          panel = addRowIfNecessary(panel);
          add(uiComponent, labelConstraints);
          myLabelWidth = Math.max(myLabelWidth, uiComponent.getPreferredSize().width);
          prevRole = null;
          break;
        case TEXT_FIELD:
          panel = addRowIfNecessary(panel);
          
          ArrangementUiComponent textLabel = ArrangementUtil.buildUiComponent(
            StdArrangementTokenUiRole.LABEL, Collections.singletonList(token.getToken()), myColorsProvider, mySettingsManager
          );
          JComponent textLabelComponent = textLabel.getUiComponent();
          add(textLabelComponent, labelConstraints);
          myLabelWidth = Math.max(myLabelWidth, textLabelComponent.getPreferredSize().width);

          panel.add(uiComponent);
          panel = addRowIfNecessary(panel);
          prevRole = null;

          myComponents.put(token.getToken(), component);
          
          if (myDefaultFocusRequestor == null) {
            myDefaultFocusRequestor = uiComponent;
          }
          break;
        default:
          if (role == StdArrangementTokenUiRole.COMBO_BOX) {
            prevTokens.add(token.getToken());
            prevRole = role;
            break;
          }
          
          panel.add(uiComponent);
          myComponents.put(token.getToken(), component);
      }
    }

    if (prevRole != null && !prevTokens.isEmpty()) {
      component = ArrangementUtil.buildUiComponent(prevRole, prevTokens, myColorsProvider, mySettingsManager);
      panel.add(component.getUiComponent());
      component.setListener(this);
      for (ArrangementSettingsToken prevToken : prevTokens) {
        myComponents.put(prevToken, component);
      }
    }
    addRowIfNecessary(panel);
  }

  @NotNull
  private MultiRowFlowPanel addRowIfNecessary(@NotNull MultiRowFlowPanel panel) {
    if (panel.getComponentCount() <= 0) {
      return panel;
    }
    add(panel, new GridBag().anchor(GridBagConstraints.WEST).weightx(1).fillCellHorizontally().coverLine());
    myRows.add(panel);
    return new MultiRowFlowPanel(
      FlowLayout.LEFT, ArrangementConstants.HORIZONTAL_GAP, ArrangementConstants.VERTICAL_GAP
    );
  }

  @Override
  public void stateChanged() {
    if (!mySkipStateChange) {
      apply();
    }
  }

  @Nullable
  private Pair<ArrangementMatchCondition, ArrangementSettingsToken> buildCondition() {
    List<ArrangementMatchCondition> conditions = ContainerUtilRt.newArrayList();
    ArrangementSettingsToken orderType = null;
    for (ArrangementUiComponent component : myComponents.values()) {
      if (!component.isEnabled() || !component.isSelected()) {
        continue;
      }
      ArrangementSettingsToken token = component.getToken();
      if (token != null && StdArrangementTokenType.ORDER.is(token)) {
        orderType = token;
      }
      else {
        conditions.add(component.getMatchCondition());
      }
    }
    if (!conditions.isEmpty()) {
      if (orderType == null) {
        orderType = StdArrangementTokens.Order.KEEP;
      }
      return Pair.create(ArrangementUtil.combine(conditions.toArray(new ArrangementMatchCondition[conditions.size()])), orderType);
    }
    else {
      return null;
    }
  }
  
  @Override
  protected void paintComponent(Graphics g) {
    if (myFocusRequestor != null) {
      if (myFocusRequestor.isFocusOwner()) {
        myFocusRequestor = null;
      }
      else {
        myFocusRequestor.requestFocusInWindow();
      }
    }
    super.paintComponent(g);
  }

  /**
   * Asks current editor to refresh its state in accordance with the arrangement rule shown at the given row.
   *
   * @param row  row index of the rule which match condition should be edited (if defined);
   *              <code>'-1'</code> as an indication that no settings should be active
   */
  public void reset(int row) {
    // Reset state.
    myRow = row;
    myFocusRequestor = myDefaultFocusRequestor;
    mySkipStateChange = true;
    try {
      for (ArrangementUiComponent component : myComponents.values()) {
        component.reset();
      }
    }
    finally {
      mySkipStateChange = false;
    }

    ArrangementMatchingRulesModel model = myControl.getModel();
    if (row < 0 || row >= model.getSize()) {
      myRow = -1;
      return;
    }

    Object element = model.getElementAt(row);
    ArrangementSettingsToken orderType = element instanceof ArrangementMatchRule ? ((ArrangementMatchRule)element).getOrderType() : null;
    final ArrangementMatchCondition condition;
    final Map<ArrangementSettingsToken, Object> conditionTokens;
    
    if (element instanceof EmptyArrangementRuleComponent) {
      // We need to disable conditions which are not applicable for empty rules (e.g. we don't want to enable 'volatile' condition
      // for java rearranger if no 'field' condition is selected.
      condition = null;
      conditionTokens = ContainerUtilRt.newHashMap();
    }
    else if (!(element instanceof StdArrangementMatchRule)) {
      return;
    }
    else {
      condition = ((StdArrangementMatchRule)element).getMatcher().getCondition();
      conditionTokens = ArrangementUtil.extractTokens(condition);
    }

    mySkipStateChange = true;
    try {
      for (ArrangementUiComponent component : myComponents.values()) {
        ArrangementSettingsToken token = component.getToken();
        if (token != null && (component.getAvailableTokens().contains(orderType) || isEnabled(condition, token))) {
          component.setEnabled(true);
          if (component.getAvailableTokens().contains(orderType)) {
            component.chooseToken(orderType);
          }
          else {
            component.setSelected(conditionTokens.containsKey(token));
          }
          Object value = conditionTokens.get(token);
          if (value != null) {
            component.setData(value);
          }
        }
      }

      refreshConditions();
    }
    finally {
      mySkipStateChange = false;
    }
  }

  /**
   * Disable conditions not applicable at the current context (e.g. disable 'synchronized' if no 'method' is selected).
   */
  private void refreshConditions() {
    Pair<ArrangementMatchCondition, ArrangementSettingsToken> pair = buildCondition();
    ArrangementMatchCondition condition = pair == null ? null : pair.first;
    for (ArrangementUiComponent component : myComponents.values()) {
      ArrangementSettingsToken token = component.getToken();
      if (token == null) {
        continue;
      }
      boolean enabled = isEnabled(condition, token);
      component.setEnabled(enabled);
      if (!enabled) {
        component.setSelected(false);
      }
    }
  }

  private boolean isEnabled(@Nullable ArrangementMatchCondition condition, @NotNull ArrangementSettingsToken token) {
    return ArrangementSectionRuleManager.isEnabled(token) || mySettingsManager.isEnabled(token, condition);
  }

  private void apply() {
    final Pair<ArrangementMatchCondition, ArrangementSettingsToken> pair = buildCondition();
    final Object modelValue;
    if (pair == null) {
      modelValue = new EmptyArrangementRuleComponent(myControl.getRowHeight(myRow));
    }
    else {
      modelValue = new StdArrangementMatchRule(new StdArrangementEntryMatcher(pair.first), pair.second);
    }
    myControl.getModel().set(myRow, modelValue);
    myControl.repaintRows(myRow, myRow, true);
  }

  public void applyAvailableWidth(int width) {
    for (MultiRowFlowPanel row : myRows) {
      row.setForcedWidth(width - myLabelWidth);
    }
    validate();
  }

  private void applyBackground(@NotNull Color color) {
    setBackground(color);
    for (JComponent component : myRows) {
      component.setBackground(color);
    }
  }

  private void onMouseClicked(@NotNull MouseEvent e) {
    if (myRow < 0) {
      return;
    }

    Point locationOnScreen = e.getLocationOnScreen();
    for (ArrangementUiComponent component : myComponents.values()) {
      Rectangle screenBounds = component.getScreenBounds();
      if (screenBounds == null || !screenBounds.contains(locationOnScreen)) {
        continue;
      }
      if (component.isEnabled()) {
        if (component.isSelected()) {
          // don't allow to remove start/end section indication
          final Set<ArrangementSettingsToken> mutexes = ArrangementSectionRuleManager.getSectionMutexes();
          if (!mutexes.contains(component.getToken())) {
            removeCondition(component);
          }
        }
        else {
          addCondition(component);
        }
      }
      apply();
      return;
    }
  }

  private void addCondition(@NotNull ArrangementUiComponent component) {
    mySkipStateChange = true;
    try {
      component.setSelected(true);
      Collection<Set<ArrangementSettingsToken>> mutexes = mySettingsManager.getMutexes();

      // Update 'mutex conditions', i.e. conditions which can't be active at the same time (e.g. type 'field' and type 'method').
      for (Set<ArrangementSettingsToken> mutex : mutexes) {
        updateMutexConditions(component, mutex);
      }
      updateMutexConditions(component, ArrangementSectionRuleManager.getSectionMutexes());
      refreshConditions();
    }
    finally {
      mySkipStateChange = false;
    }
  }

  private void updateMutexConditions(@NotNull ArrangementUiComponent component, @NotNull Set<ArrangementSettingsToken> mutex) {
    if (!mutex.contains(component.getToken())) {
      return;
    }
    for (ArrangementSettingsToken key : mutex) {
      if (key.equals(component.getToken())) {
        continue;
      }
      ArrangementUiComponent c = myComponents.get(key);
      if (c != null && c.isEnabled()) {
        removeCondition(c);
      }
    }
  }

  private void removeCondition(@NotNull ArrangementUiComponent component) {
    component.setSelected(false);
    refreshConditions();
  }

  @Override
  public String toString() {
    return "matching rule editor";
  }
}
