/*
 * 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.psi.codeStyle.arrangement;

import com.intellij.application.options.codeStyle.arrangement.color.ArrangementColorsProvider;
import com.intellij.lang.Language;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.codeStyle.arrangement.match.*;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementAtomMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementCompositeMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchCondition;
import com.intellij.psi.codeStyle.arrangement.model.ArrangementMatchConditionVisitor;
import com.intellij.psi.codeStyle.arrangement.std.*;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.ContainerUtilRt;
import com.intellij.util.text.CharArrayUtil;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.*;

/**
 * @author Denis Zhdanov
 * @since 7/17/12 11:24 AM
 */
public class ArrangementUtil {
  private static final Logger LOG = Logger.getInstance(ArrangementUtil.class);

  private ArrangementUtil() {
  }

  //region Serialization

  @Nullable
  public static ArrangementSettings readExternal(@NotNull Element element, @NotNull Language language) {
    ArrangementSettingsSerializer serializer = getSerializer(language);
    if (serializer == null) {
      LOG.error("Can't find serializer for language: " + language.getDisplayName() + "(" + language.getID() + ")");
      return null;
    }

    return serializer.deserialize(element);
  }

  public static void writeExternal(@NotNull Element element, @NotNull ArrangementSettings settings, @NotNull Language language) {
    ArrangementSettingsSerializer serializer = getSerializer(language);
    if (serializer == null) {
      LOG.error("Can't find serializer for language: " + language.getDisplayName() + "(" + language.getID() + ")");
      return;
    }

    serializer.serialize(settings, element);
  }

  @Nullable
  private static ArrangementSettingsSerializer getSerializer(@NotNull Language language) {
    Rearranger<?> rearranger = Rearranger.EXTENSION.forLanguage(language);
    return rearranger == null ? null : rearranger.getSerializer();
  }
  
  //endregion

  @NotNull
  public static ArrangementMatchCondition combine(@NotNull ArrangementMatchCondition... nodes) {
    final ArrangementCompositeMatchCondition result = new ArrangementCompositeMatchCondition();
    final ArrangementMatchConditionVisitor visitor = new ArrangementMatchConditionVisitor() {
      @Override
      public void visit(@NotNull ArrangementAtomMatchCondition node) {
        result.addOperand(node);
      }

      @Override
      public void visit(@NotNull ArrangementCompositeMatchCondition node) {
        for (ArrangementMatchCondition operand : node.getOperands()) {
          operand.invite(this);
        }
      }
    };
    for (ArrangementMatchCondition node : nodes) {
      node.invite(visitor);
    }
    return result.getOperands().size() == 1 ? result.getOperands().iterator().next() : result;
  }

  //region ArrangementEntry

  /**
   * Tries to build a text range on the given arguments basis. Expands to the line start/end if possible.
   * <p/>
   * This method is expected to be used in a situation when we want to arrange complete rows.
   * Example:
   * <pre>
   *   class Test {
   *        void test() {
   *        }
   *      int i;
   *   }
   * </pre>
   * Suppose, we want to locate fields before methods. We can move the exact field and method range then but indent will be broken,
   * i.e. we'll get the result below:
   * <pre>
   *   class Test {
   *        int i;
   *      void test() {
   *        }
   *   }
   * </pre>
   * We can expand field and method range to the whole lines and that would allow to achieve the desired result:
   * <pre>
   *   class Test {
   *      int i;
   *        void test() {
   *        }
   *   }
   * </pre>
   * However, this method is expected to just return given range if there are multiple distinct elements at the same line:
   * <pre>
   *   class Test {
   *     void test1(){} void test2() {} int i;
   *   }
   * </pre>
   * 
   * @param initialRange  anchor range
   * @param document      target document against which the ranges are built
   * @return              expanded range if possible; <code>null</code> otherwise
   */
  @NotNull
  public static TextRange expandToLineIfPossible(@NotNull TextRange initialRange, @NotNull Document document) {
    CharSequence text = document.getCharsSequence();
    String ws = " \t";
    
    int startLine = document.getLineNumber(initialRange.getStartOffset());
    int lineStartOffset = document.getLineStartOffset(startLine);
    int i = CharArrayUtil.shiftBackward(text, lineStartOffset + 1, initialRange.getStartOffset() - 1, ws);
    if (i != lineStartOffset) {
      return initialRange;
    }

    int endLine = document.getLineNumber(initialRange.getEndOffset());
    int lineEndOffset = document.getLineEndOffset(endLine);
    i = CharArrayUtil.shiftForward(text, initialRange.getEndOffset(), lineEndOffset, ws);
    
    return i == lineEndOffset ? TextRange.create(lineStartOffset, lineEndOffset) : initialRange;
  }
  //endregion
  
  @Nullable
  public static ArrangementSettingsToken parseType(@NotNull ArrangementMatchCondition condition) throws IllegalArgumentException {
    final Ref<ArrangementSettingsToken> result = new Ref<ArrangementSettingsToken>();
    condition.invite(new ArrangementMatchConditionVisitor() {
      @Override
      public void visit(@NotNull ArrangementAtomMatchCondition condition) {
        if (StdArrangementTokenType.ENTRY_TYPE.is(condition.getType())) {
          result.set(condition.getType());
        }
      }

      @Override
      public void visit(@NotNull ArrangementCompositeMatchCondition condition) {
        for (ArrangementMatchCondition c : condition.getOperands()) {
          c.invite(this);
          if (result.get() != null) {
            return;
          }
        } 
      }
    });

    return result.get();
  }

  public static <T> Set<T> flatten(@NotNull Iterable<? extends Iterable<T>> data) {
    Set<T> result = ContainerUtilRt.newHashSet();
    for (Iterable<T> i : data) {
      for (T t : i) {
        result.add(t);
      }
    }
    return result;
  }

  @NotNull
  public static Map<ArrangementSettingsToken, Object> extractTokens(@NotNull ArrangementMatchCondition condition) {
    final Map<ArrangementSettingsToken, Object> result = ContainerUtilRt.newHashMap();
    condition.invite(new ArrangementMatchConditionVisitor() {
      @Override
      public void visit(@NotNull ArrangementAtomMatchCondition condition) {
        ArrangementSettingsToken type = condition.getType();
        Object value = condition.getValue();
        result.put(condition.getType(), type.equals(value) ? null : value); 
      }

      @Override
      public void visit(@NotNull ArrangementCompositeMatchCondition condition) {
        for (ArrangementMatchCondition operand : condition.getOperands()) {
          operand.invite(this);
        } 
      }
    });
    return result;
  }

  @Nullable
  public static ArrangementEntryMatcher buildMatcher(@NotNull ArrangementMatchCondition condition) {
    final Ref<ArrangementEntryMatcher> result = new Ref<ArrangementEntryMatcher>();
    final Stack<CompositeArrangementEntryMatcher> composites = new Stack<CompositeArrangementEntryMatcher>();
    ArrangementMatchConditionVisitor visitor = new ArrangementMatchConditionVisitor() {
      @Override
      public void visit(@NotNull ArrangementAtomMatchCondition condition) {
        ArrangementEntryMatcher matcher = buildMatcher(condition);
        if (matcher == null) {
          return;
        }
        if (composites.isEmpty()) {
          result.set(matcher);
        }
        else {
          composites.peek().addMatcher(matcher);
        } 
      }

      @Override
      public void visit(@NotNull ArrangementCompositeMatchCondition condition) {
        composites.push(new CompositeArrangementEntryMatcher());
        try {
          for (ArrangementMatchCondition operand : condition.getOperands()) {
            operand.invite(this);
          }
        }
        finally {
          CompositeArrangementEntryMatcher matcher = composites.pop();
          if (composites.isEmpty()) {
            result.set(matcher);
          }
        }
      }
    };
    condition.invite(visitor);
    return result.get();
  }

  @Nullable
  public static ArrangementEntryMatcher buildMatcher(@NotNull ArrangementAtomMatchCondition condition) {
    if (StdArrangementTokenType.ENTRY_TYPE.is(condition.getType())) {
      return new ByTypeArrangementEntryMatcher(condition.getType());
    }
    else if (StdArrangementTokenType.MODIFIER.is(condition.getType())) {
      return new ByModifierArrangementEntryMatcher(condition.getType());
    }
    else if (StdArrangementTokens.Regexp.NAME.equals(condition.getType())) {
      return new ByNameArrangementEntryMatcher(condition.getValue().toString());
    }
    else if (StdArrangementTokens.Regexp.XML_NAMESPACE.equals(condition.getType())) {
      return new ByNamespaceArrangementEntryMatcher(condition.getValue().toString());
    }
    else {
      return null;
    }
  }

  @NotNull
  public static ArrangementUiComponent buildUiComponent(@NotNull StdArrangementTokenUiRole role,
                                                        @NotNull List<ArrangementSettingsToken> tokens,
                                                        @NotNull ArrangementColorsProvider colorsProvider,
                                                        @NotNull ArrangementStandardSettingsManager settingsManager)
    throws IllegalArgumentException
  {
    for (ArrangementUiComponent.Factory factory : Extensions.getExtensions(ArrangementUiComponent.Factory.EP_NAME)) {
      ArrangementUiComponent result = factory.build(role, tokens, colorsProvider, settingsManager);
      if (result != null) {
        return result;
      }
    }
    throw new IllegalArgumentException("Unsupported UI token role " + role);
  }

  @NotNull
  public static List<CompositeArrangementSettingsToken> flatten(@NotNull CompositeArrangementSettingsToken base) {
    List<CompositeArrangementSettingsToken> result = ContainerUtilRt.newArrayList();
    Queue<CompositeArrangementSettingsToken> toProcess = ContainerUtilRt.newLinkedList(base);
    while (!toProcess.isEmpty()) {
      CompositeArrangementSettingsToken token = toProcess.remove();
      result.add(token);
      toProcess.addAll(token.getChildren());
    }
    return result;
  }

  //region Arrangement Sections
  @NotNull
  public static List<StdArrangementMatchRule> collectMatchRules(@NotNull List<ArrangementSectionRule> sections) {
    final List<StdArrangementMatchRule> matchRules = ContainerUtil.newArrayList();
    for (ArrangementSectionRule section : sections) {
      matchRules.addAll(section.getMatchRules());
    }
    return matchRules;
  }
  //endregion
}
