text:
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.psi.util;

import com.intellij.lang.ASTNode;
import com.intellij.lang.Language;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.psi.search.PsiElementProcessor;
import com.intellij.psi.search.PsiElementProcessor.CollectElements;
import com.intellij.psi.search.PsiElementProcessor.CollectFilteredElements;
import com.intellij.psi.search.PsiElementProcessor.FindElement;
import com.intellij.psi.stubs.StubBase;
import com.intellij.psi.stubs.StubElement;
import com.intellij.psi.templateLanguages.OuterLanguageElement;
import com.intellij.psi.tree.IElementType;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Consumer;
import com.intellij.util.PairProcessor;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.*;
import java.util.function.Predicate;

import static com.intellij.psi.SyntaxTraverser.psiTraverser;

public class PsiTreeUtil {
  private static final Logger LOG = Logger.getInstance("#com.intellij.psi.util.PsiTreeUtil");

  private static final Key<Object> MARKER = Key.create("PsiTreeUtil.copyElements.MARKER");
  private static final Class[] WS = {PsiWhiteSpace.class};
  private static final Class[] WS_COMMENTS = {PsiWhiteSpace.class, PsiComment.class};

  /**
   * Checks whether one element in the psi tree is under another.
   *
   * @param ancestor parent candidate. {@code false} will be returned if ancestor is null.
   * @param element  child candidate
   * @param strict   whether return true if ancestor and parent are the same.
   * @return true if element has ancestor as its parent somewhere in the hierarchy and false otherwise.
   */
  @Contract("null, _, _ -> false")
  public static boolean isAncestor(@Nullable PsiElement ancestor, @NotNull PsiElement element, boolean strict) {
    if (ancestor == null) return false;
    // fast path to avoid loading tree
    if (ancestor instanceof StubBasedPsiElement && ((StubBasedPsiElement)ancestor).getStub() != null ||
        element instanceof StubBasedPsiElement && ((StubBasedPsiElement)element).getStub() != null) {
      if (ancestor.getContainingFile() != element.getContainingFile()) return false;
    }

    boolean stopAtFileLevel = !(ancestor instanceof PsiFile || ancestor instanceof PsiDirectory);

    PsiElement parent = strict ? element.getParent() : element;
    while (true) {
      if (parent == null) return false;
      if (parent.equals(ancestor)) return true;
      if (stopAtFileLevel && parent instanceof PsiFile) return false;
      parent = parent.getParent();
    }
  }

  /**
   * Checks whether one element in the psi tree is under another in {@link PsiElement#getContext()}  hierarchy.
   *
   * @param ancestor parent candidate. {@code false} will be returned if ancestor is null.
   * @param element  child candidate
   * @param strict   whether return true if ancestor and parent are the same.
   * @return true if element has ancestor as its parent somewhere in the hierarchy and false otherwise.
   */
  @Contract("null, _, _ -> false")
  public static boolean isContextAncestor(@Nullable PsiElement ancestor, @NotNull PsiElement element, boolean strict) {
    if (ancestor == null) return false;
    boolean stopAtFileLevel = !(ancestor instanceof PsiFile || ancestor instanceof PsiDirectory);
    PsiElement parent = strict ? element.getContext() : element;
    while (true) {
      if (parent == null) return false;
      if (parent.equals(ancestor)) return true;
      if (stopAtFileLevel && parent instanceof PsiFile) {
        final PsiElement context = parent.getContext();
        if (context == null) return false;
      }
      parent = parent.getContext();
    }
  }

  @Nullable
  @SuppressWarnings("Duplicates")
  public static PsiElement findCommonParent(@NotNull List<? extends PsiElement> elements) {
    if (elements.isEmpty()) return null;

    PsiElement toReturn = null;
    for (PsiElement element : elements) {
      if (element == null) continue;
      toReturn = toReturn == null ? element : findCommonParent(toReturn, element);
      if (toReturn == null) return null;
    }
    return toReturn;
  }

  @Nullable
  @SuppressWarnings("Duplicates")
  public static PsiElement findCommonParent(@NotNull PsiElement... elements) {
    if (elements.length == 0) return null;

    PsiElement toReturn = null;
    for (PsiElement element : elements) {
      if (element == null) continue;
      toReturn = toReturn == null ? element : findCommonParent(toReturn, element);
      if (toReturn == null) return null;
    }
    return toReturn;
  }

  @Nullable
  public static PsiElement findCommonParent(@NotNull PsiElement element1, @NotNull PsiElement element2) {
    // optimization
    if (element1 == element2) return element1;
    final PsiFile containingFile = element1.getContainingFile();
    final PsiElement topLevel = containingFile == element2.getContainingFile() ? containingFile : null;

    int depth1 = getDepth(element1, topLevel);
    int depth2 = getDepth(element2, topLevel);

    PsiElement parent1 = element1;
    PsiElement parent2 = element2;
    while (depth1 > depth2) {
      parent1 = parent1.getParent();
      depth1--;
    }
    while (depth2 > depth1) {
      parent2 = parent2.getParent();
      depth2--;
    }
    while (parent1 != null && parent2 != null && !parent1.equals(parent2)) {
      parent1 = parent1.getParent();
      parent2 = parent2.getParent();
    }
    return parent1;
  }

  @Contract(pure = true)
  private static int getDepth(@NotNull PsiElement element, @Nullable PsiElement topLevel) {
    int depth=0;
    PsiElement parent = element;
    while (parent != topLevel && parent != null) {
      depth++;
      parent = parent.getParent();
    }
    return depth;
  }

  @Nullable
  public static PsiElement findCommonContext(@NotNull Collection<? extends PsiElement> elements) {
    if (elements.isEmpty()) return null;
    PsiElement toReturn = null;
    for (PsiElement element : elements) {
      if (element == null) continue;
      toReturn = toReturn == null ? element : findCommonContext(toReturn, element);
      if (toReturn == null) return null;
    }
    return toReturn;
  }

  @Nullable
  public static PsiElement findCommonContext(@NotNull PsiElement element1, @NotNull PsiElement element2) {
    // optimization
    if (element1 == element2) return element1;
    final PsiFile containingFile = element1.getContainingFile();
    final PsiElement topLevel = containingFile == element2.getContainingFile() ? containingFile : null;

    int depth1 = getContextDepth(element1, topLevel);
    int depth2 = getContextDepth(element2, topLevel);

    PsiElement parent1 = element1;
    PsiElement parent2 = element2;
    while(depth1 > depth2 && parent1 != null) {
      parent1 = parent1.getContext();
      depth1--;
    }
    while(depth2 > depth1 && parent2 != null) {
      parent2 = parent2.getContext();
      depth2--;
    }
    while(parent1 != null && parent2 != null && !parent1.equals(parent2)) {
      parent1 = parent1.getContext();
      parent2 = parent2.getContext();
    }
    return parent1;
  }

  private static int getContextDepth(@NotNull PsiElement element, @Nullable PsiElement topLevel) {
    int depth=0;
    PsiElement parent = element;
    while (parent != topLevel && parent != null) {
      depth++;
      parent = parent.getContext();
    }
    return depth;
  }

  /** See {@link #findChildOfType(PsiElement, Class, boolean, Class)}. */
  @Nullable
  @Contract("null, _ -> null")
  public static <T extends PsiElement> T findChildOfType(@Nullable PsiElement element, @NotNull Class<T> aClass) {
    return findChildOfType(element, aClass, true, null);
  }

  /** See {@link #findChildOfType(PsiElement, Class, boolean, Class)}. */
  @Nullable
  @Contract("null, _, _ -> null")
  public static <T extends PsiElement> T findChildOfType(@Nullable PsiElement element, @NotNull Class<T> aClass, boolean strict) {
    return findChildOfType(element, aClass, strict, null);
  }

  /**
   * Recursive (depth first) search for first element of a given class.
   *
   * @param element a PSI element to start search from
   * @param strict  if false the {@code element} is also included in the search
   * @param aClass  element type to search for
   * @param stopAt  element type to abort the search at
   * @param <T>     type to cast found element to
   * @return first found element, or {@code null} if nothing found
   */
  @Nullable
  @Contract("null, _, _, _ -> null")
  public static <T extends PsiElement> T findChildOfType(@Nullable PsiElement element,
                                                         @NotNull Class<T> aClass,
                                                         boolean strict,
                                                         @Nullable Class<? extends PsiElement> stopAt) {
    if (element == null) return null;

    FindElement<PsiElement> processor = new PsiElementProcessor.FindElement<PsiElement>() {
      @Override
      public boolean execute(@NotNull PsiElement each) {
        if (strict && each == element) return true;
        if (aClass.isInstance(each)) return setFound(each);
        return stopAt == null || !stopAt.isInstance(each);
      }
    };
    processElements(element, processor);
    return aClass.cast(processor.getFoundElement());
  }

  /** See {@link #findChildOfAnyType(PsiElement, boolean, Class[])}. */
  @SafeVarargs
  @Nullable
  @Contract("null, _ -> null")
  public static <T extends PsiElement> T findChildOfAnyType(@Nullable PsiElement element, @NotNull Class<? extends T>... classes) {
    return findChildOfAnyType(element, true, classes);
  }

  /**
   * Recursive (depth first) search for first element of any of given {@code classes}.
   *
   * @param element a PSI element to start search from.
   * @param strict  if false the {@code element} is also included in the search.
   * @param classes element types to search for.
   * @param <T>     type to cast found element to.
   * @return first found element, or {@code null} if nothing found.
   */
  @SafeVarargs
  @Nullable
  @Contract("null, _, _ -> null")
  public static <T extends PsiElement> T findChildOfAnyType(@Nullable PsiElement element,
                                                            boolean strict,
                                                            @NotNull Class<? extends T>... classes) {
    if (element == null) return null;

    FindElement<PsiElement> processor = new FindElement<PsiElement>() {
      @Override
      public boolean execute(@NotNull PsiElement each) {
        if (strict && each == element) return true;
        if (instanceOf(each, classes)) {
          return setFound(each);
        }
        return true;
      }
    };

    processElements(element, processor);
    @SuppressWarnings("unchecked") T t = (T)processor.getFoundElement();
    return t;
  }

  /** See {@link #findChildrenOfAnyType(PsiElement, boolean, Class[])}. */
  @NotNull
  public static <T extends PsiElement> Collection<T> findChildrenOfType(@Nullable PsiElement element, @NotNull Class<? extends T> aClass) {
    return findChildrenOfAnyType(element, true, aClass);
  }

  /** See {@link #findChildrenOfAnyType(PsiElement, boolean, Class[])}. */
  @SafeVarargs
  @NotNull
  public static <T extends PsiElement> Collection<T> findChildrenOfAnyType(@Nullable PsiElement element,
                                                                           @NotNull Class<? extends T>... classes) {
    return findChildrenOfAnyType(element, true, classes);
  }

  /**
   * Recursive (depth first) search for all elements of any of given {@code classes}.
   *
   * @param element a PSI element to start search from.
   * @param strict  if false the {@code element} is also included in the search.
   * @param classes element types to search for.
   * @param <T>     type to cast found elements to.
   * @return {@code Collection<T>} of all found elements, or empty {@code List<T>} if nothing found.
   */
  @SafeVarargs
  @NotNull
  public static <T extends PsiElement> Collection<T> findChildrenOfAnyType(@Nullable PsiElement element,
                                                                           boolean strict,
                                                                           @NotNull Class<? extends T>... classes) {
    if (element == null) return ContainerUtil.emptyList();

    CollectElements<T> processor = new CollectElements<T>() {
      @Override
      public boolean execute(@NotNull T each) {
        if (strict && each == element) return true;
        if (instanceOf(each, classes)) {
          return super.execute(each);
        }
        return true;
      }
    };
    processElements(element, processor);
    return processor.getCollection();
  }

  /**
   * Non-recursive search for element of type T amongst given {@code element} children.
   *
   * @param element a PSI element to start search from.
   * @param aClass  element type to search for.
   * @param <T>     element type to search for.
   * @return first found element, or null if nothing found.
   */
  @Nullable
  @Contract("null, _ -> null")
  public static <T extends PsiElement> T getChildOfType(@Nullable PsiElement element, @NotNull Class<T> aClass) {
    if (element == null) return null;
    for (PsiElement child = element.getFirstChild(); child != null; child = child.getNextSibling()) {
      if (aClass.isInstance(child)) {
        return aClass.cast(child);
      }
    }
    return null;
  }

  @Nullable
  public static PsiElement findFirstParent(@Nullable PsiElement element, Condition<PsiElement> condition) {
    return findFirstParent(element, false, condition);
  }

  @Nullable
  public static PsiElement findFirstParent(@Nullable PsiElement element, boolean strict, Condition<PsiElement> condition) {
    if (strict && element != null) {
      element = element.getParent();
    }

    while (element != null) {
      if (condition.value(element)) {
        return element;
      }
      element = element.getParent();
    }
    return null;
  }

  @Nullable
  public static PsiElement findFirstContext(@Nullable PsiElement element, boolean strict, Condition<PsiElement> condition) {
    if (strict && element != null) {
      element = element.getContext();
    }

    while (element != null) {
      if (condition.value(element)) {
        return element;
      }
      element = element.getContext();
    }
    return null;
  }

  @NotNull
  public static <T extends PsiElement> T getRequiredChildOfType(@NotNull PsiElement element, @NotNull Class<T> aClass) {
    final T child = getChildOfType(element, aClass);
    assert child != null : "Missing required child of type " + aClass.getName();
    return child;
  }

  @Nullable
  public static <T extends PsiElement> T[] getChildrenOfType(@Nullable PsiElement element, @NotNull Class<T> aClass) {
    if (element == null) return null;
    List<T> result = getChildrenOfTypeAsList(element, aClass);
    return result.isEmpty() ? null : ArrayUtil.toObjectArray(result, aClass);
  }

  @SafeVarargs
  @NotNull
  public static <T extends PsiElement> List<T> getChildrenOfAnyType(@Nullable PsiElement element, @NotNull Class<? extends T>... classes) {
    if (element == null) return ContainerUtil.emptyList();

    List<T> result = null;
    for (PsiElement child = element.getFirstChild(); child != null; child = child.getNextSibling()) {
      if (instanceOf(child, classes)) {
        if (result == null) result = ContainerUtil.newSmartList();
        @SuppressWarnings("unchecked") T t = (T)child;
        result.add(t);
      }
    }
    if (result == null) {
      return ContainerUtil.emptyList();
    }
    return result;
  }

  @NotNull
  public static <T extends PsiElement> List<T> getChildrenOfTypeAsList(@Nullable PsiElement element, @NotNull Class<T> aClass) {
    if (element == null) return Collections.emptyList();

    List<T> result = null;
    for (PsiElement child = element.getFirstChild(); child != null; child = child.getNextSibling()) {
      if (aClass.isInstance(child)) {
        if (result == null) result = new SmartList<>();
        result.add(aClass.cast(child));
      }
    }
    return result == null ? Collections.emptyList() : result;
  }

  @NotNull
  public static List<PsiElement> getElementsOfRange(@NotNull PsiElement start, @NotNull PsiElement end) {
    List<PsiElement> result = new ArrayList<>();
    for (PsiElement e = start; e != end; e = e.getNextSibling()) {
      if (e == null) throw new IllegalArgumentException("Invalid range: " + start + ".." + end);
      result.add(e);
    }
    result.add(end);
    return result;
  }

  @Nullable
  public static <T extends PsiElement> T getStubChildOfType(@Nullable PsiElement element, @NotNull Class<T> aClass) {
    if (element == null) return null;
    StubElement<?> stub = element instanceof StubBasedPsiElement ? ((StubBasedPsiElement)element).getStub() : null;
    if (stub == null) {
      return getChildOfType(element, aClass);
    }
    for (StubElement childStub : stub.getChildrenStubs()) {
      PsiElement child = childStub.getPsi();
      if (aClass.isInstance(child)) {
        return aClass.cast(child);
      }
    }
    return null;
  }

  @NotNull
  public static <T extends PsiElement> List<T> getStubChildrenOfTypeAsList(@Nullable PsiElement element, @NotNull Class<T> aClass) {
    if (element == null) return Collections.emptyList();
    StubElement<?> stub = element instanceof StubBasedPsiElement ? ((StubBasedPsiElement)element).getStub() : null;
    if (stub == null) {
      return getChildrenOfTypeAsList(element, aClass);
    }

    List<T> result = new SmartList<>();
    for (StubElement childStub : stub.getChildrenStubs()) {
      PsiElement child = childStub.getPsi();
      if (aClass.isInstance(child)) {
        result.add(aClass.cast(child));
      }
    }
    return result;
  }

  public static boolean instanceOf(Object object, Class<?>... classes) {
    if (object != null && classes != null) {
      for (Class<?> c : classes) {
        if (c.isInstance(object)) return true;
      }
    }
    return false;
  }

  /**
   * Returns a direct child of the specified element which has any of the specified classes.
   *
   * @param element the element to get the child for.
   * @param classes the array of classes.
   * @return the element, or null if none was found.
   * @since 5.1
   */
  @SafeVarargs
  @Nullable
  @Contract("null, _ -> null")
  public static <T extends PsiElement> T getChildOfAnyType(@Nullable PsiElement element, @NotNull Class<? extends T>... classes) {
    if (element == null) return null;
    for (PsiElement child = element.getFirstChild(); child != null; child = child.getNextSibling()) {
      for (Class<? extends T> aClass : classes) {
        if (aClass.isInstance(child)) {
          return aClass.cast(child);
        }
      }
    }
    return null;
  }

  @Nullable
  @Contract("null, _ -> null")
  public static <T extends PsiElement> T getNextSiblingOfType(@Nullable PsiElement sibling, @NotNull Class<T> aClass) {
    if (sibling == null) return null;
    for (PsiElement child = sibling.getNextSibling(); child != null; child = child.getNextSibling()) {
      if (aClass.isInstance(child)) {
        return aClass.cast(child);
      }
    }
    return null;
  }

  @Nullable
  @Contract("null, _ -> null")
  public static <T extends PsiElement> T getPrevSiblingOfType(@Nullable PsiElement sibling, @NotNull Class<T> aClass) {
    if (sibling == null) return null;
    for (PsiElement child = sibling.getPrevSibling(); child != null; child = child.getPrevSibling()) {
      if (aClass.isInstance(child)) {
        return aClass.cast(child);
      }
    }
    return null;
  }

  @Nullable
  @Contract("null, _ -> null")
  public static <T extends PsiElement> T getTopmostParentOfType(@Nullable PsiElement element, @NotNull Class<T> aClass) {
    T answer = getParentOfType(element, aClass);

    do {
      T next = getParentOfType(answer, aClass);
      if (next == null) break;
      answer = next;
    }
    while (true);

    return answer;
  }

  @Nullable
  @Contract("null, _ -> null")
  public static <T extends PsiElement> T getParentOfType(@Nullable PsiElement element, @NotNull Class<T> aClass) {
    return getParentOfType(element, aClass, true);
  }

  @Nullable
  @Contract("null -> null")
  public static PsiElement getStubOrPsiParent(@Nullable PsiElement element) {
    if (element instanceof StubBasedPsiElement) {
      StubBase stub = (StubBase)((StubBasedPsiElement)element).getStub();
      if (stub != null) {
        final StubElement parentStub = stub.getParentStub();
        return parentStub != null ? parentStub.getPsi() : null;
      }
    }
    return element != null ? element.getParent() : null;
  }

  @Nullable
  @Contract("null, _ -> null")
  public static <E extends PsiElement> E getStubOrPsiParentOfType(@Nullable PsiElement element, @NotNull Class<E> parentClass) {
    if (element instanceof StubBasedPsiElement) {
      StubBase stub = (StubBase)((StubBasedPsiElement)element).getStub();
      if (stub != null) {
        @SuppressWarnings("unchecked") E e = (E)stub.getParentStubOfType(parentClass);
        return e;
      }
    }
    return getParentOfType(element, parentClass);
  }

  @SafeVarargs
  @Nullable
  @Contract("null, _, _, _ -> null")
  public static <T extends PsiElement> T getContextOfType(@Nullable PsiElement element,
                                                          @NotNull Class<T> aClass,
                                                          boolean strict,
                                                          Class<? extends PsiElement>... stopAt) {
    if (element == null) return null;
    if (strict) {
      element = element.getContext();
    }

    while (element != null && !aClass.isInstance(element)) {
      if (instanceOf(element, stopAt)) return null;
      element = element.getContext();
    }

    return aClass.cast(element);
  }

  @Nullable
  @Contract("null, _, _ -> null")
  public static <T extends PsiElement> T getContextOfType(@Nullable PsiElement element,
                                                          @NotNull Class<? extends T> aClass,
                                                          boolean strict) {
    return getContextOfType(element, strict, aClass);
  }

  @SafeVarargs
  @Nullable
  public static <T extends PsiElement> T getContextOfType(@Nullable PsiElement element, @NotNull Class<? extends T>... classes) {
    return getContextOfType(element, true, classes);
  }

  @SafeVarargs
  @Nullable
  @Contract("null, _, _ -> null")
  public static <T extends PsiElement> T getContextOfType(@Nullable PsiElement element,
                                                          boolean strict,
                                                          @NotNull Class<? extends T>... classes) {
    if (element == null) return null;
    if (strict) {
      element = element.getContext();
    }

    while (element != null && !instanceOf(element, classes)) {
      element = element.getContext();
    }

    @SuppressWarnings("unchecked") T t = (T)element;
    return t;
  }

  @Nullable
  @Contract("null, _, _ -> null")
  public static <T extends PsiElement> T getParentOfType(@Nullable PsiElement element, @NotNull Class<T> aClass, boolean strict) {
    return getParentOfType(element, aClass, strict, -1);
  }

  @Contract("null, _, _, _ -> null")
  public static <T extends PsiElement> T getParentOfType(@Nullable PsiElement element, @NotNull Class<T> aClass, boolean strict, int minStartOffset) {
    if (element == null) {
      return null;
    }

    if (strict) {
      if (element instanceof PsiFile) {
        return null;
      }
      element = element.getParent();
    }

    while (element != null && (minStartOffset == -1 || element.getNode().getStartOffset() >= minStartOffset)) {
      if (aClass.isInstance(element)) {
        return aClass.cast(element);
      }
      if (element instanceof PsiFile) {
        return null;
      }
      element = element.getParent();
    }

    return null;
  }

  @SafeVarargs
  @Nullable
  @Contract("null, _, _, _ -> null")
  public static <T extends PsiElement> T getParentOfType(@Nullable PsiElement element,
                                                         @NotNull Class<T> aClass,
                                                         boolean strict,
                                                         @NotNull Class<? extends PsiElement>... stopAt) {
    if (element == null) return null;
    if (strict) {
      if (element instanceof PsiFile) return null;
      element = element.getParent();
    }

    while (element != null && !aClass.isInstance(element)) {
      if (instanceOf(element, stopAt)) return null;
      if (element instanceof PsiFile) return null;
      element = element.getParent();
    }

    return aClass.cast(element);
  }

  @NotNull
  public static <T extends PsiElement> List<T> collectParents(@NotNull PsiElement element,
                                                              @NotNull Class<? extends T> parent,
                                                              boolean includeMyself, @NotNull Predicate<? super PsiElement> stopCondition) {
    if (!includeMyself) {
      element = element.getParent();
    }
    List<T> parents = new SmartList<>();
    while (element != null) {
      if (stopCondition.test(element)) break;
      if (parent.isInstance(element)) {
        parents.add(parent.cast(element));
      }
      element = element.getParent();
    }
    return parents;
  }

  @Nullable
  public static PsiElement findSiblingForward(@NotNull final PsiElement element,
                                              @NotNull final IElementType elementType,
                                              @Nullable final Consumer<PsiElement> consumer) {
    return findSiblingForward(element, elementType, true, consumer);
  }

  @Nullable
  public static PsiElement findSiblingForward(@NotNull final PsiElement element,
                                              @NotNull final IElementType elementType,
                                              boolean strict,
                                              @Nullable final Consumer<? super PsiElement> consumer) {
    for (PsiElement e = strict ? element.getNextSibling() : element; e != null; e = e.getNextSibling()) {
      if (elementType.equals(e.getNode().getElementType())) {
        return e;
      }
      if (consumer != null) consumer.consume(e);
    }
    return null;
  }

  @Nullable
  public static PsiElement findSiblingBackward(@NotNull final PsiElement element,
                                               @NotNull final IElementType elementType,
                                               @Nullable final Consumer<PsiElement> consumer) {
    return findSiblingBackward(element, elementType, true, consumer);
  }

  @Nullable
  public static PsiElement findSiblingBackward(@NotNull final PsiElement element,
                                               @NotNull final IElementType elementType,
                                               boolean strict,
                                               @Nullable final Consumer<? super PsiElement> consumer) {
    for (PsiElement e = strict ? element.getPrevSibling() : element; e != null; e = e.getPrevSibling()) {
      if (elementType.equals(e.getNode().getElementType())) {
        return e;
      }
      if (consumer != null) consumer.consume(e);
    }
    return null;
  }

  @Nullable
  @Contract("null, _ -> null")
  public static PsiElement skipSiblingsForward(@Nullable PsiElement element, @NotNull Class... elementClasses) {
    if (element == null) return null;
    for (PsiElement e = element.getNextSibling(); e != null; e = e.getNextSibling()) {
      if (!instanceOf(e, elementClasses)) {
        return e;
      }
    }
    return null;
  }

  @Nullable
  @Contract("null -> null")
  public static PsiElement skipWhitespacesForward(@Nullable PsiElement element) {
    return skipSiblingsForward(element, WS);
  }

  @Nullable
  @Contract("null -> null")
  public static PsiElement skipWhitespacesAndCommentsForward(@Nullable PsiElement element) {
    return skipSiblingsForward(element, WS_COMMENTS);
  }

  @Nullable
  @Contract("null, _ -> null")
  public static PsiElement skipSiblingsBackward(@Nullable PsiElement element, @NotNull Class... elementClasses) {
    if (element == null) return null;
    for (PsiElement e = element.getPrevSibling(); e != null; e = e.getPrevSibling()) {
      if (!instanceOf(e, elementClasses)) {
        return e;
      }
    }
    return null;
  }

  @Nullable
  @Contract("null -> null")
  public static PsiElement skipWhitespacesBackward(@Nullable PsiElement element) {
    return skipSiblingsBackward(element, WS);
  }

  @Nullable
  @Contract("null -> null")
  public static PsiElement skipWhitespacesAndCommentsBackward(@Nullable PsiElement element) {
    return skipSiblingsBackward(element, WS_COMMENTS);
  }

  @Nullable
  @Contract("null, _ -> null")
  public static PsiElement skipParentsOfType(@Nullable PsiElement element, @NotNull Class... parentClasses) {
    if (element == null) return null;
    for (PsiElement e = element.getParent(); e != null; e = e.getParent()) {
      if (!instanceOf(e, parentClasses)) {
        return e;
      }
    }
    return null;
  }

  @SafeVarargs
  @Nullable
  @Contract("null, _ -> null")
  public static <T extends PsiElement> T getParentOfType(@Nullable final PsiElement element,
                                                         @NotNull final Class<? extends T>... classes) {
    if (element == null || element instanceof PsiFile) return null;
    PsiElement parent = element.getParent();
    if (parent == null) return null;
    return getNonStrictParentOfType(parent, classes);
  }

  @SafeVarargs
  @Nullable
  @Contract("null, _ -> null")
  public static <T extends PsiElement> T getNonStrictParentOfType(@Nullable final PsiElement element,
                                                                  @NotNull final Class<? extends T>... classes) {
    PsiElement run = element;
    while (run != null) {
      if (instanceOf(run, classes)) {
        @SuppressWarnings("unchecked") T t = (T)run;
        return t;
      }
      if (run instanceof PsiFile) break;
      run = run.getParent();
    }

    return null;
  }

  @NotNull
  @Contract(pure=true)
  public static PsiElement[] collectElements(@Nullable PsiElement element, @NotNull PsiElementFilter filter) {
    CollectFilteredElements<PsiElement> processor = new CollectFilteredElements<>(filter);
    processElements(element, processor);
    return processor.toArray();
  }

  @SafeVarargs
  @NotNull
  @Contract(pure=true)
  public static <T extends PsiElement> Collection<T> collectElementsOfType(@Nullable PsiElement element, @NotNull Class<T>... classes) {
    return findChildrenOfAnyType(element, false, classes);
  }

  @Contract("null, _ -> true")
  public static boolean processElements(@Nullable PsiElement element, @NotNull PsiElementProcessor processor) {
    if (element == null) return true;
    if (element instanceof PsiCompiledElement || !element.isPhysical()) {
      // DummyHolders cannot be visited by walking visitors because children/parent relationship is broken there
      //noinspection unchecked
      if (!processor.execute(element)) return false;
      for (PsiElement child : element.getChildren()) {
        if (!processElements(child, processor)) return false;
      }
      return true;
    }
    final boolean[] result = {true};
    element.accept(new PsiRecursiveElementWalkingVisitor() {
      @Override
      public void visitElement(PsiElement element) {
        //noinspection unchecked
        if (processor.execute(element)) {
          super.visitElement(element);
        }
        else {
          stopWalking();
          result[0] = false;
        }
      }
    });

    return result[0];
  }

  public static boolean processElements(@NotNull PsiElementProcessor processor, @Nullable PsiElement... elements) {
    if (elements == null || elements.length == 0) return true;
    for (PsiElement element : elements) {
      if (!processElements(element, processor)) return false;
    }
    return true;
  }

  public static void mark(@NotNull PsiElement element, @NotNull Object marker) {
    element.getNode().putCopyableUserData(MARKER, marker);
  }

  @Nullable
  public static PsiElement releaseMark(@NotNull PsiElement root, @NotNull Object marker) {
    ASTNode node = root.getNode();
    if (marker.equals(node.getCopyableUserData(MARKER))) {
      node.putCopyableUserData(MARKER, null);
      return root;
    }
    else {
      PsiElement child = root.getFirstChild();
      while (child != null) {
        final PsiElement result = releaseMark(child, marker);
        if (result != null) return result;
        child = child.getNextSibling();
      }
      return null;
    }
  }

  @Nullable
  @Contract(pure=true)
  public static <T extends PsiElement> T findElementOfClassAtOffset(@NotNull PsiFile file,
                                                                    int offset,
                                                                    @NotNull Class<T> clazz,
                                                                    boolean strictStart) {
    final List<PsiFile> psiRoots = file.getViewProvider().getAllFiles();
    T result = null;
    for (PsiElement root : psiRoots) {
      final PsiElement elementAt = root.findElementAt(offset);
      if (elementAt != null) {
        final T parent = getParentOfType(elementAt, clazz, strictStart);
        if (parent != null) {
          final TextRange range = parent.getTextRange();
          if (!strictStart || range.getStartOffset() == offset) {
            if (result == null || result.getTextRange().getEndOffset() > range.getEndOffset()) {
              result = parent;
            }
          }
        }
      }
    }

    return result;
  }

  @SafeVarargs
  @Nullable
  @Contract(pure=true)
  public static <T extends PsiElement> T findElementOfClassAtOffsetWithStopSet(@NotNull PsiFile file,
                                                                               int offset,
                                                                               @NotNull Class<T> clazz,
                                                                               boolean strictStart,
                                                                               @NotNull Class<? extends PsiElement>... stopAt) {
    final List<PsiFile> psiRoots = file.getViewProvider().getAllFiles();
    T result = null;
    for (PsiElement root : psiRoots) {
      final PsiElement elementAt = root.findElementAt(offset);
      if (elementAt != null) {
        final T parent = getParentOfType(elementAt, clazz, strictStart, stopAt);
        if (parent != null) {
          final TextRange range = parent.getTextRange();
          if (!strictStart || range.getStartOffset() == offset) {
            if (result == null || result.getTextRange().getEndOffset() > range.getEndOffset()) {
              result = parent;
            }
          }
        }
      }
    }

    return result;
  }

  /**
   * @return maximal element of specified Class starting at startOffset exactly and ending not farther than endOffset
   */
  @Nullable
  @Contract(pure=true)
  public static <T extends PsiElement> T findElementOfClassAtRange(@NotNull PsiFile file,
                                                                   int startOffset,
                                                                   int endOffset,
                                                                   @NotNull Class<T> clazz) {
    final FileViewProvider viewProvider = file.getViewProvider();
    T result = null;
    for (Language lang : viewProvider.getLanguages()) {
      PsiElement elementAt = viewProvider.findElementAt(startOffset, lang);
      T run = getParentOfType(elementAt, clazz, false);
      T prev = run;
      while (run != null && run.getTextRange().getStartOffset() == startOffset &&
             run.getTextRange().getEndOffset() <= endOffset) {
        prev = run;
        run = getParentOfType(run, clazz);
      }

      if (prev == null) continue;
      final int elementStartOffset = prev.getTextRange().getStartOffset();
      final int elementEndOffset = prev.getTextRange().getEndOffset();
      if (elementStartOffset != startOffset || elementEndOffset > endOffset) continue;

      if (result == null || result.getTextRange().getEndOffset() < elementEndOffset) {
        result = prev;
      }
    }

    return result;
  }

  @NotNull
  public static PsiElement getDeepestFirst(@NotNull PsiElement elt) {
    @NotNull PsiElement res = elt;
    do {
      final PsiElement firstChild = res.getFirstChild();
      if (firstChild == null) return res;
      res = firstChild;
    }
    while (true);
  }

  @NotNull
  public static PsiElement getDeepestLast(@NotNull PsiElement elt) {
    @NotNull PsiElement res = elt;
    do {
      final PsiElement lastChild = res.getLastChild();
      if (lastChild == null) return res;
      res = lastChild;
    }
    while (true);
  }

  @Nullable
  public static PsiElement prevLeaf(@NotNull PsiElement current) {
    final PsiElement prevSibling = current.getPrevSibling();
    if (prevSibling != null) return lastChild(prevSibling);
    final PsiElement parent = current.getParent();
    if (parent == null || parent instanceof PsiFile) return null;
    return prevLeaf(parent);
  }

  @Nullable
  public static PsiElement nextLeaf(@NotNull PsiElement current) {
    final PsiElement nextSibling = current.getNextSibling();
    if (nextSibling != null) return firstChild(nextSibling);
    final PsiElement parent = current.getParent();
    if (parent == null || parent instanceof PsiFile) return null;
    return nextLeaf(parent);
  }

  public static PsiElement lastChild(@NotNull PsiElement element) {
    PsiElement lastChild = element.getLastChild();
    if (lastChild != null) return lastChild(lastChild);
    return element;
  }

  public static PsiElement firstChild(@NotNull final PsiElement element) {
    PsiElement child = element.getFirstChild();
    if (child != null) return firstChild(child);
    return element;
  }

  @Nullable
  public static PsiElement prevLeaf(@NotNull final PsiElement element, final boolean skipEmptyElements) {
    PsiElement prevLeaf = prevLeaf(element);
    while (skipEmptyElements && prevLeaf != null && prevLeaf.getTextLength() == 0) prevLeaf = prevLeaf(prevLeaf);
    return prevLeaf;
  }

  @Nullable
  public static PsiElement prevVisibleLeaf(@NotNull final PsiElement element) {
    PsiElement prevLeaf = prevLeaf(element, true);
    while (prevLeaf != null && StringUtil.isEmptyOrSpaces(prevLeaf.getText())) prevLeaf = prevLeaf(prevLeaf, true);
    return prevLeaf;
  }

  @Nullable
  public static PsiElement nextVisibleLeaf(@NotNull final PsiElement element) {
    PsiElement nextLeaf = nextLeaf(element, true);
    while (nextLeaf != null && StringUtil.isEmptyOrSpaces(nextLeaf.getText())) nextLeaf = nextLeaf(nextLeaf, true);
    return nextLeaf;
  }

  @Nullable
  public static PsiElement nextLeaf(@NotNull PsiElement element, final boolean skipEmptyElements) {
    PsiElement nextLeaf = nextLeaf(element);
    while (skipEmptyElements && nextLeaf != null && nextLeaf.getTextLength() == 0) nextLeaf = nextLeaf(nextLeaf);
    return nextLeaf;
  }

  public static boolean hasErrorElements(@NotNull PsiElement element) {
    return !psiTraverser(element).traverse().filter(PsiErrorElement.class).isEmpty();
  }

  @NotNull
  public static PsiElement[] filterAncestors(@NotNull PsiElement[] elements) {
    if (LOG.isDebugEnabled()) {
      for (PsiElement element : elements) {
        LOG.debug("element = " + element);
      }
    }

    ArrayList<PsiElement> filteredElements = new ArrayList<>();
    ContainerUtil.addAll(filteredElements, elements);

    int previousSize;
    do {
      previousSize = filteredElements.size();
      outer:
      for (PsiElement element : filteredElements) {
        for (PsiElement element2 : filteredElements) {
          if (element == element2) continue;
          if (isAncestor(element, element2, false)) {
            if (LOG.isDebugEnabled()) {
              LOG.debug("removing " + element2);
            }
            filteredElements.remove(element2);
            break outer;
          }
        }
      }
    }
    while (filteredElements.size() != previousSize);

    if (LOG.isDebugEnabled()) {
      for (PsiElement element : filteredElements) {
        LOG.debug("filtered element = " + element);
      }
    }

    return PsiUtilCore.toPsiElementArray(filteredElements);
  }

  public static boolean treeWalkUp(@NotNull final PsiScopeProcessor processor,
                                   @NotNull final PsiElement entrance,
                                   @Nullable final PsiElement maxScope,
                                   @NotNull final ResolveState state) {
    PsiElement prevParent = entrance;
    PsiElement scope = entrance;

    while (scope != null) {
      if (!scope.processDeclarations(processor, state, prevParent, entrance)) return false;

      if (scope == maxScope) break;
      prevParent = scope;
      scope = prevParent.getContext();
    }

    return true;
  }

  public static boolean treeWalkUp(@NotNull final PsiElement entrance,
                                   @Nullable final PsiElement maxScope,
                                   @NotNull PairProcessor<PsiElement, PsiElement> eachScopeAndLastParent) {
    PsiElement prevParent = null;
    PsiElement scope = entrance;

    while (scope != null) {
      if (!eachScopeAndLastParent.process(scope, prevParent)) return false;

      if (scope == maxScope) break;
      prevParent = scope;
      scope = prevParent.getContext();
    }

    return true;

  }

  @NotNull
  public static PsiElement findPrevParent(@NotNull PsiElement ancestor, @NotNull PsiElement descendant) {
    PsiElement cur = descendant;
    while (cur != null) {
      final PsiElement parent = cur.getParent();
      if (parent == ancestor) {
        return cur;
      }
      cur = parent;
    }
    throw new AssertionError(descendant + " is not a descendant of " + ancestor);
  }

  public static List<PsiElement> getInjectedElements(@NotNull OuterLanguageElement outerLanguageElement) {
    PsiElement psi = outerLanguageElement.getContainingFile().getViewProvider().getPsi(outerLanguageElement.getLanguage());
    TextRange injectionRange = outerLanguageElement.getTextRange();
    List<PsiElement> res = ContainerUtil.newArrayList();

    assert psi != null : outerLanguageElement;
    for (PsiElement element = psi.findElementAt(injectionRange.getStartOffset());
         element != null && injectionRange.intersectsStrict(element.getTextRange());
         element = element.getNextSibling()) {
      res.add(element);
    }

    return res;
  }

  @Nullable
  public static PsiElement getDeepestVisibleFirst(@NotNull PsiElement psiElement) {
    PsiElement first = getDeepestFirst(psiElement);
    if (StringUtil.isEmptyOrSpaces(first.getText())) {
      first = nextVisibleLeaf(first);
    }
    return first;
  }

  @Nullable
  public static PsiElement getDeepestVisibleLast(@NotNull PsiElement psiElement) {
    PsiElement last = getDeepestLast(psiElement);
    if (StringUtil.isEmptyOrSpaces(last.getText())) {
      last = prevVisibleLeaf(last);
    }
    return last;
  }

  //<editor-fold desc="Deprecated stuff.">
  /** use {@link SyntaxTraverser#psiTraverser()} (to be removed in IDEA 2019) */
  @Deprecated
  public static <T extends PsiElement> Iterator<T> childIterator(@NotNull PsiElement element, @NotNull Class<T> aClass) {
    return psiTraverser().children(element).filter(aClass).iterator();
  }
  //</editor-fold>
}


text:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Maui.Trading.Evaluation
{
    public class TradingLog
    {
        private IList<Order> myOrders;

        public TradingLog()
        {
            myOrders = new List<Order>();
        }

        public IEnumerable<Order> Orders
        {
            get
            {
                return myOrders;
            }
        }

        public void Add( Order order )
        {
            myOrders.Add( order );
        }
    }
}

redpajama_set_name: RedPajamaGithub


text:
const fs = require('fs');
const assert = require('assert');

function parsePackageJsonVersion(versionString) {
    const versionRgx = /(\d+\.\d+)\.(\d+)($|\-)/;
    const match = versionString.match(versionRgx);
    assert(match !== null, "package.json 'version' should match", () => versionRgx.toString());
    return { majorMinor: match[1], patch: match[2] };
}

/** e.g. 0-dev.20170707 */
function getNightlyPatch(plainPatch) {
    // We're going to append a representation of the current time at the end of the current version.
    // String.prototype.toISOString() returns a 24-character string formatted as 'YYYY-MM-DDTHH:mm:ss.sssZ',
    // but we'd prefer to just remove separators and limit ourselves to YYYYMMDDHHmmss.
    // UTC time will always be implicit here.
    const now = new Date();
    const timeStr = now.toISOString().replace(/:|T|\.|-/g, "").slice(0, 14);

    return `${plainPatch}-dev.${timeStr}`;
}

const content = fs.readFileSync('package.json');
const packageJsonValue = JSON.parse(content);

const { majorMinor, patch } = parsePackageJsonVersion(packageJsonValue.version);
const nightlyPatch = getNightlyPatch(patch);
packageJsonValue.version = `${majorMinor}.${nightlyPatch}`;
fs.writeFileSync('package.json', JSON.stringify(packageJsonValue, /*replacer:*/ undefined, /*space:*/ 4));
fs.writeFileSync('js/version.ts', `export const version = "${packageJsonValue.version}";\n`);


text:
#ifndef PLAYER_WIDGET_H
#define PLAYER_WIDGET_H

#include <QtMultimedia/QMediaPlayer>
#include <QtWidgets/QWidget>

namespace Ui {
class PlayerWidget;
}

class Player;
class PlaylistModel;

class PlayerWidget : public QWidget
{
    Q_OBJECT

public:
    explicit PlayerWidget(QWidget *parent = 0);
    ~PlayerWidget();

    Player *player() const;
    void setPlayer(Player *mediaPlayer);

Q_SIGNALS:
    void fullScreenChanged(bool fullScreen);
    void mediaChanged();
    void commute();
    void stopped();

public Q_SLOTS:
    void scrollVolume(int numSteps);

private Q_SLOTS:
    void metaDataChanged();
    void statusChanged(QMediaPlayer::MediaStatus status);
    void bufferingProgress(int progress);
    void displayErrorMessage();

private:
    Ui::PlayerWidget *ui;

    void setTrackInfo(const QString &info);
    void setStatusInfo(const QString &info);
    void handleCursor(QMediaPlayer::MediaStatus status);

    Player *m_player;
    PlaylistModel *m_playlistModel;

    QString m_trackInfo;
    QString m_statusInfo;
};

#endif // PLAYER_WIDGET_H


text:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>

    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
        <encoder charset="utf-8">
            <Pattern>[%date{yyyy-MM-dd HH:mm:ss}] [%-5level] %logger %line --%mdc{client} %msg%n</Pattern>
        </encoder>
    </appender>

    <logger name="org.apache.zookeeper" level="OFF" />
    <logger name="org.apache.curator" level="OFF" />

    <!-- INFO 输出到 info.log、ERROR 输出到 error.log -->
    <root level="DEBUG" name="com.xhh.demo">
        <appender-ref ref="stdout"/>
    </root>

</configuration>


text:
use strict;
use Data::Dumper;
use Bio::EnsEMBL::Registry;
use Bio::EnsEMBL::Funcgen::DBSQL::DBAdaptor;
use Bio::EnsEMBL::Funcgen::ProbeMapping;
use Getopt::Long;

my $registry;
my $species;

GetOptions (
   'registry=s'            => \$registry,
   'species=s'             => \$species,
);

use Bio::EnsEMBL::Utils::Logger;
my $logger = Bio::EnsEMBL::Utils::Logger->new();
$logger->init_log;

Bio::EnsEMBL::Registry->load_all($registry);

my $meta_adaptor = Bio::EnsEMBL::Registry->get_adaptor($species, 'core', 'MetaContainer');

$logger->info("Fetching assembly for $species\n");
my $assembly = $meta_adaptor->single_value_by_key('assembly.default',0);
$logger->info("Done.\n");

$logger->info("Fetching gene build for $species\n");
my $gene_build = $meta_adaptor->single_value_by_key('genebuild.last_geneset_update',0);
$logger->info("Done.\n");

$logger->info("Fetching release version for $species\n");
my $release_version = $meta_adaptor->get_schema_version();
$logger->info("Done.\n");

my $release_date_time = localtime;

$logger->info("Insert meta data in probe_mapping table for $species\n");

my $probe_mapping_adaptor = Bio::EnsEMBL::Registry->get_adaptor($species, 'funcgen', 'ProbeMapping');

my $remmove_probemapping = $probe_mapping_adaptor->fetch_single_object;
if ($remmove_probemapping){
	$probe_mapping_adaptor->_delete($remmove_probemapping);
}

my $probe_mapping = Bio::EnsEMBL::Funcgen::ProbeMapping->new(

    -assembly  			 => $assembly,
    -gene_build_version  => $gene_build,
    -release_version     => $release_version,
    -release_date        => $release_date_time,

);

$probe_mapping_adaptor->store($probe_mapping);

$logger->info("Done.\n");


text:
package org.dynmap.fabric_1_14_4;

import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import it.unimi.dsi.fastutil.longs.Long2ObjectLinkedOpenHashMap;
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerChunkEvents;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerWorldEvents;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.FluidBlock;
import net.minecraft.block.Material;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.network.ClientConnection;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.command.ServerCommandSource;
import net.minecraft.server.network.ServerPlayNetworkHandler;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ChunkHolder;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.IdList;
import net.minecraft.util.Identifier;
//import net.minecraft.util.collection.IdList;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.CollisionView;
import net.minecraft.world.EmptyBlockView;
import net.minecraft.world.IWorld;
import net.minecraft.world.World;
//import net.minecraft.world.WorldAccess;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.ChunkSection;
import net.minecraft.world.chunk.ChunkStatus;
import net.minecraft.world.chunk.WorldChunk;
import org.dynmap.*;
import org.dynmap.common.BiomeMap;
import org.dynmap.common.DynmapCommandSender;
import org.dynmap.common.DynmapListenerManager;
import org.dynmap.common.DynmapPlayer;
import org.dynmap.common.chunk.GenericChunkCache;
import org.dynmap.fabric_1_14_4.command.DmapCommand;
import org.dynmap.fabric_1_14_4.event.BlockEvents;
import org.dynmap.fabric_1_14_4.event.ChunkDataEvents;
import org.dynmap.fabric_1_14_4.event.CustomServerLifecycleEvents;
import org.dynmap.fabric_1_14_4.event.PlayerEvents;
import org.dynmap.fabric_1_14_4.mixin.ThreadedAnvilChunkStorageAccessor;
import org.dynmap.fabric_1_14_4.command.DmarkerCommand;
import org.dynmap.fabric_1_14_4.command.DynmapCommand;
import org.dynmap.fabric_1_14_4.command.DynmapExpCommand;
import org.dynmap.fabric_1_14_4.permissions.FilePermissions;
import org.dynmap.fabric_1_14_4.permissions.OpPermissions;
import org.dynmap.fabric_1_14_4.permissions.PermissionProvider;
import org.dynmap.permissions.PermissionsHandler;
import org.dynmap.renderer.DynmapBlockState;

import java.io.File;
import java.util.*;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.regex.Pattern;

public class DynmapPlugin {
    // FIXME: Fix package-private fields after splitting is done
    DynmapCore core;
    private PermissionProvider permissions;
    private boolean core_enabled;
    public GenericChunkCache sscache;
    public PlayerList playerList;
    MapManager mapManager;
    /**
     * Server is set when running and unset at shutdown.
     */
    private net.minecraft.server.MinecraftServer server;
    public static DynmapPlugin plugin;
    ChatHandler chathandler;
    private HashMap<String, Integer> sortWeights = new HashMap<String, Integer>();
    // Drop world load ticket after 30 seconds
    private long worldIdleTimeoutNS = 30 * 1000000000L;
    private HashMap<String, FabricWorld> worlds = new HashMap<String, FabricWorld>();
    private CollisionView last_world;
    private FabricWorld last_fworld;
    private Map<String, FabricPlayer> players = new HashMap<String, FabricPlayer>();
    //TODO private ForgeMetrics metrics;
    private HashSet<String> modsused = new HashSet<String>();
    private FabricServer fserver;
    private boolean tickregistered = false;
    // TPS calculator
    double tps;
    long lasttick;
    long avgticklen;
    // Per tick limit, in nsec
    long perTickLimit = (50000000); // 50 ms
    private boolean useSaveFolder = true;

    private static final int SIGNPOST_ID = 63;
    private static final int WALLSIGN_ID = 68;

    private static final String[] TRIGGER_DEFAULTS = {"blockupdate", "chunkpopulate", "chunkgenerate"};

    static final Pattern patternControlCode = Pattern.compile("(?i)\\u00A7[0-9A-FK-OR]");

    DynmapPlugin() {
        plugin = this;
        // Fabric events persist between server instances
        ServerLifecycleEvents.SERVER_STARTING.register(this::serverStart);
        CommandRegistrationCallback.EVENT.register((dispatcher, dedicated) -> registerCommands(dispatcher));
        CustomServerLifecycleEvents.SERVER_STARTED_PRE_WORLD_LOAD.register(this::serverStarted);
        ServerLifecycleEvents.SERVER_STOPPING.register(this::serverStop);
    }

    int getSortWeight(String name) {
        return sortWeights.getOrDefault(name, 0);
    }

    void setSortWeight(String name, int wt) {
        sortWeights.put(name, wt);
    }

    void dropSortWeight(String name) {
        sortWeights.remove(name);
    }

    public static class BlockUpdateRec {
        CollisionView w;
        String wid;
        int x, y, z;
    }

    ConcurrentLinkedQueue<BlockUpdateRec> blockupdatequeue = new ConcurrentLinkedQueue<BlockUpdateRec>();

    public static DynmapBlockState[] stateByID;

    private Map<String, LongOpenHashSet> knownloadedchunks = new HashMap<String, LongOpenHashSet>();
    private boolean didInitialKnownChunks = false;

    private void addKnownChunk(FabricWorld fw, ChunkPos pos) {
        LongOpenHashSet cset = knownloadedchunks.get(fw.getName());
        if (cset == null) {
            cset = new LongOpenHashSet();
            knownloadedchunks.put(fw.getName(), cset);
        }
        cset.add(pos.toLong());
    }

    private void removeKnownChunk(FabricWorld fw, ChunkPos pos) {
        LongOpenHashSet cset = knownloadedchunks.get(fw.getName());
        if (cset != null) {
            cset.remove(pos.toLong());
        }
    }

    private boolean checkIfKnownChunk(FabricWorld fw, ChunkPos pos) {
        LongOpenHashSet cset = knownloadedchunks.get(fw.getName());
        if (cset != null) {
            return cset.contains(pos.toLong());
        }
        return false;
    }

    /**
     * Initialize block states (org.dynmap.blockstate.DynmapBlockState)
     */
    public void initializeBlockStates() {
        stateByID = new DynmapBlockState[512 * 32];    // Simple map - scale as needed
        Arrays.fill(stateByID, DynmapBlockState.AIR); // Default to air

        IdList<BlockState> bsids = Block.STATE_IDS;

        DynmapBlockState basebs = null;
        Block baseb = null;
        int baseidx = 0;

        Iterator<BlockState> iter = bsids.iterator();
    	DynmapBlockState.Builder bld = new DynmapBlockState.Builder();
        while (iter.hasNext()) {
            BlockState bs = iter.next();
            int idx = bsids.getId(bs);
            if (idx >= stateByID.length) {
                int plen = stateByID.length;
    			stateByID = Arrays.copyOf(stateByID, idx*11/10); // grow array by 10%
                Arrays.fill(stateByID, plen, stateByID.length, DynmapBlockState.AIR);
            }
            Block b = bs.getBlock();
            // If this is new block vs last, it's the base block state
            if (b != baseb) {
                basebs = null;
                baseidx = idx;
                baseb = b;
            }

            Identifier ui = Registry.BLOCK.getId(b);
            if (ui == null) {
                continue;
            }
            String bn = ui.getNamespace() + ":" + ui.getPath();
            // Only do defined names, and not "air"
            if (!bn.equals(DynmapBlockState.AIR_BLOCK)) {
                Material mat = bs.getMaterial();
                String statename = "";
                for (net.minecraft.state.property.Property<?> p : bs.getProperties()) {
                    if (statename.length() > 0) {
                        statename += ",";
                    }
                    statename += p.getName() + "=" + bs.get(p).toString();
                }
                int lightAtten = bs.isFullOpaque(EmptyBlockView.INSTANCE, BlockPos.ORIGIN) ? 15 : (bs.isTranslucent(EmptyBlockView.INSTANCE, BlockPos.ORIGIN) ? 0 : 1);
                //Log.info("statename=" + bn + "[" + statename + "], lightAtten=" + lightAtten);
                // Fill in base attributes
                bld.setBaseState(basebs).setStateIndex(idx - baseidx).setBlockName(bn).setStateName(statename).setMaterial(mat.toString()).setLegacyBlockID(idx).setAttenuatesLight(lightAtten);
				if (mat.isSolid()) { bld.setSolid(); }
				if (mat == Material.AIR) { bld.setAir(); }
				if (mat == Material.WOOD) { bld.setLog(); }
				if (mat == Material.LEAVES) { bld.setLeaves(); }
				if ((!bs.getFluidState().isEmpty()) && !(bs.getBlock() instanceof FluidBlock)) {
					bld.setWaterlogged();
				}
                DynmapBlockState dbs = bld.build(); // Build state
                stateByID[idx] = dbs;
                if (basebs == null) { basebs = dbs; }
            }
        }
        for (int gidx = 0; gidx < DynmapBlockState.getGlobalIndexMax(); gidx++) {
            DynmapBlockState bs = DynmapBlockState.getStateByGlobalIndex(gidx);
            //Log.info(gidx + ":" + bs.toString() + ", gidx=" + bs.globalStateIndex + ", sidx=" + bs.stateIndex);
        }
    }

    public static final Item getItemByID(int id) {
        return Item.byRawId(id);
    }

    private static Biome[] biomelist = null;

    public static final Biome[] getBiomeList() {
        if (biomelist == null) {
            biomelist = new Biome[256];
            Iterator<Biome> iter = Registry.BIOME.iterator();
            while (iter.hasNext()) {
                Biome b = iter.next();
                int bidx = Registry.BIOME.getRawId(b);
                if (bidx >= biomelist.length) {
                    biomelist = Arrays.copyOf(biomelist, bidx + biomelist.length);
                }
                biomelist[bidx] = b;
            }
        }
        return biomelist;
    }

    public static final ClientConnection getNetworkManager(ServerPlayNetworkHandler nh) {
        return nh.connection;
    }

    FabricPlayer getOrAddPlayer(ServerPlayerEntity player) {
        String name = player.getName().getString();
        FabricPlayer fp = players.get(name);
        if (fp != null) {
            fp.player = player;
        } else {
            fp = new FabricPlayer(this, player);
            players.put(name, fp);
        }
        return fp;
    }

    static class ChatMessage {
        String message;
        ServerPlayerEntity sender;
    }

    ConcurrentLinkedQueue<ChatMessage> msgqueue = new ConcurrentLinkedQueue<ChatMessage>();

    public static class ChatHandler {
        private final DynmapPlugin plugin;

        ChatHandler(DynmapPlugin plugin) {
            this.plugin = plugin;
        }

        public void handleChat(ServerPlayerEntity player, String message) {
            if (!message.startsWith("/")) {
                ChatMessage cm = new ChatMessage();
                cm.message = message;
                cm.sender = player;
                plugin.msgqueue.add(cm);
            }
        }
    }

    private void serverStart(MinecraftServer server) {
        // Set the server so we don't NPE during setup
        this.server = server;
        this.fserver = new FabricServer(this, server);
        this.onEnable();
    }

    private void serverStarted(MinecraftServer server) {
        this.onStart();
        if (core != null) {
            core.serverStarted();
        }
    }

    private void serverStop(MinecraftServer server) {
        this.onDisable();
        this.server = null;
    }

    public boolean isOp(String player) {
        String[] ops = server.getPlayerManager().getOpList().getNames();

        for (String op : ops) {
            if (op.equalsIgnoreCase(player)) {
                return true;
            }
        }

        // TODO: Consider whether cheats are enabled for integrated server
        return server.isSinglePlayer() && player.equalsIgnoreCase(server.getUserName());
    }

    boolean hasPerm(PlayerEntity psender, String permission) {
        PermissionsHandler ph = PermissionsHandler.getHandler();
        if ((ph != null) && (psender != null) && ph.hasPermission(psender.getName().getString(), permission)) {
            return true;
        }
        return permissions.has(psender, permission);
    }

    boolean hasPermNode(PlayerEntity psender, String permission) {
        PermissionsHandler ph = PermissionsHandler.getHandler();
        if ((ph != null) && (psender != null) && ph.hasPermissionNode(psender.getName().getString(), permission)) {
            return true;
        }
        return permissions.hasPermissionNode(psender, permission);
    }

    Set<String> hasOfflinePermissions(String player, Set<String> perms) {
        Set<String> rslt = null;
        PermissionsHandler ph = PermissionsHandler.getHandler();
        if (ph != null) {
            rslt = ph.hasOfflinePermissions(player, perms);
        }
        Set<String> rslt2 = hasOfflinePermissions(player, perms);
        if ((rslt != null) && (rslt2 != null)) {
            Set<String> newrslt = new HashSet<String>(rslt);
            newrslt.addAll(rslt2);
            rslt = newrslt;
        } else if (rslt2 != null) {
            rslt = rslt2;
        }
        return rslt;
    }

    boolean hasOfflinePermission(String player, String perm) {
        PermissionsHandler ph = PermissionsHandler.getHandler();
        if (ph != null) {
            if (ph.hasOfflinePermission(player, perm)) {
                return true;
            }
        }
        return permissions.hasOfflinePermission(player, perm);
    }

    void setChatHandler(ChatHandler chatHandler) {
        plugin.chathandler = chatHandler;
    }

    public class TexturesPayload {
        public long timestamp;
        public String profileId;
        public String profileName;
        public boolean isPublic;
        public Map<String, ProfileTexture> textures;

    }

    public class ProfileTexture {
        public String url;
    }

    public void loadExtraBiomes(String mcver) {
        int cnt = 0;
        BiomeMap.loadWellKnownByVersion(mcver);

        Biome[] list = getBiomeList();

        for (int i = 0; i < list.length; i++) {
            Biome bb = list[i];
            if (bb != null) {
                String id = Registry.BIOME.getId(bb).getPath();
                float tmp = bb.getTemperature(), hum = bb.getRainfall();
                int watermult = bb.getWaterColor();
                Log.verboseinfo("biome[" + i + "]: hum=" + hum + ", tmp=" + tmp + ", mult=" + Integer.toHexString(watermult));

                BiomeMap bmap = BiomeMap.byBiomeID(i);
                if (bmap.isDefault()) {
                    bmap = new BiomeMap(i, id, tmp, hum);
                    Log.verboseinfo("Add custom biome [" + bmap.toString() + "] (" + i + ")");
                    cnt++;
                } else {
                    bmap.setTemperature(tmp);
                    bmap.setRainfall(hum);
                }
                if (watermult != -1) {
                    bmap.setWaterColorMultiplier(watermult);
                    Log.verboseinfo("Set watercolormult for " + bmap.toString() + " (" + i + ") to " + Integer.toHexString(watermult));
                }
            }
        }
        if (cnt > 0)
            Log.info("Added " + cnt + " custom biome mappings");
    }

    private String[] getBiomeNames() {
        Biome[] list = getBiomeList();
        String[] lst = new String[list.length];
        for (int i = 0; i < list.length; i++) {
            Biome bb = list[i];
            if (bb != null) {
                lst[i] = Registry.BIOME.getId(bb).getPath();
            }
        }
        return lst;
    }

    public void onEnable() {
        /* Get MC version */
        String mcver = server.getVersion();

        /* Load extra biomes */
        loadExtraBiomes(mcver);
        /* Set up player login/quit event handler */
        registerPlayerLoginListener();

        /* Initialize permissions handler */
        permissions = FilePermissions.create();
        if (permissions == null) {
            permissions = new OpPermissions(new String[]{"webchat", "marker.icons", "marker.list", "webregister", "stats", "hide.self", "show.self"});
        }
        /* Get and initialize data folder */
        File dataDirectory = new File("dynmap");

        if (!dataDirectory.exists()) {
            dataDirectory.mkdirs();
        }

        /* Instantiate core */
        if (core == null) {
            core = new DynmapCore();
        }

        /* Inject dependencies */
        core.setPluginJarFile(DynmapMod.jarfile);
        core.setPluginVersion(DynmapMod.ver);
        core.setMinecraftVersion(mcver);
        core.setDataFolder(dataDirectory);
        core.setServer(fserver);
        core.setTriggerDefault(TRIGGER_DEFAULTS);
        core.setBiomeNames(getBiomeNames());

        if (!core.initConfiguration(null)) {
            return;
        }
        // Extract default permission example, if needed
        File filepermexample = new File(core.getDataFolder(), "permissions.yml.example");
        core.createDefaultFileFromResource("/permissions.yml.example", filepermexample);

        DynmapCommonAPIListener.apiInitialized(core);
    }

    private DynmapCommand dynmapCmd;
    private DmapCommand dmapCmd;
    private DmarkerCommand dmarkerCmd;
    private DynmapExpCommand dynmapexpCmd;

    public void registerCommands(CommandDispatcher<ServerCommandSource> cd) {
        dynmapCmd = new DynmapCommand(this);
        dmapCmd = new DmapCommand(this);
        dmarkerCmd = new DmarkerCommand(this);
        dynmapexpCmd = new DynmapExpCommand(this);
        dynmapCmd.register(cd);
        dmapCmd.register(cd);
        dmarkerCmd.register(cd);
        dynmapexpCmd.register(cd);

        Log.info("Register commands");
    }

    public void onStart() {
        initializeBlockStates();
        /* Enable core */
        if (!core.enableCore(null)) {
            return;
        }
        core_enabled = true;
        VersionCheck.runCheck(core);
        // Get per tick time limit
        perTickLimit = core.getMaxTickUseMS() * 1000000;
        // Prep TPS
        lasttick = System.nanoTime();
        tps = 20.0;

        /* Register tick handler */
        if (!tickregistered) {
            ServerTickEvents.END_SERVER_TICK.register(server -> fserver.tickEvent(server));
            tickregistered = true;
        }

        playerList = core.playerList;
        sscache = new GenericChunkCache(core.getSnapShotCacheSize(), core.useSoftRefInSnapShotCache());
        /* Get map manager from core */
        mapManager = core.getMapManager();

        /* Load saved world definitions */
        loadWorlds();

        /* Initialized the currently loaded worlds */
        if (server.getWorlds() != null) {
            for (ServerWorld world : server.getWorlds()) {
                FabricWorld w = this.getWorld(world);
                /*NOTYET - need rest of forge
                if(DimensionManager.getWorld(world.provider.getDimensionId()) == null) { // If not loaded
                    w.setWorldUnloaded();
                }
                */
            }
        }
        for (FabricWorld w : worlds.values()) {
            if (core.processWorldLoad(w)) {   /* Have core process load first - fire event listeners if good load after */
                if (w.isLoaded()) {
                    core.listenerManager.processWorldEvent(DynmapListenerManager.EventType.WORLD_LOAD, w);
                }
            }
        }
        core.updateConfigHashcode();

        /* Register our update trigger events */
        registerEvents();
        Log.info("Register events");

        //DynmapCommonAPIListener.apiInitialized(core);

        Log.info("Enabled");
    }

    public void onDisable() {
        DynmapCommonAPIListener.apiTerminated();

        //if (metrics != null) {
        //	metrics.stop();
        //	metrics = null;
        //}
        /* Save worlds */
        saveWorlds();

        /* Purge tick queue */
        fserver.clearTaskQueue();

        /* Disable core */
        core.disableCore();
        core_enabled = false;

        if (sscache != null) {
            sscache.cleanup();
            sscache = null;
        }

        Log.info("Disabled");
    }

    // TODO: Clean a bit
    public void handleCommand(ServerCommandSource commandSource, String cmd, String[] args) throws CommandSyntaxException {
        DynmapCommandSender dsender;
        ServerPlayerEntity psender = null;

        // getPlayer throws a CommandSyntaxException, so getEntity and instanceof for safety
        if (commandSource.getEntity() instanceof ServerPlayerEntity) {
            psender = commandSource.getPlayer();
        }

        if (psender != null) {
            // FIXME: New Player? Why not query the current player list.
            dsender = new FabricPlayer(this, psender);
        } else {
            dsender = new FabricCommandSender(commandSource);
        }

        core.processCommand(dsender, cmd, cmd, args);
    }

    public class PlayerTracker {
        public void onPlayerLogin(ServerPlayerEntity player) {
            if (!core_enabled) return;
            final DynmapPlayer dp = getOrAddPlayer(player);
            /* This event can be called from off server thread, so push processing there */
            core.getServer().scheduleServerTask(new Runnable() {
                public void run() {
                    core.listenerManager.processPlayerEvent(DynmapListenerManager.EventType.PLAYER_JOIN, dp);
                }
            }, 2);
        }

        public void onPlayerLogout(ServerPlayerEntity player) {
            if (!core_enabled) return;
            final DynmapPlayer dp = getOrAddPlayer(player);
            final String name = player.getName().getString();
            /* This event can be called from off server thread, so push processing there */
            core.getServer().scheduleServerTask(new Runnable() {
                public void run() {
                    core.listenerManager.processPlayerEvent(DynmapListenerManager.EventType.PLAYER_QUIT, dp);
                    players.remove(name);
                }
            }, 0);
        }

        public void onPlayerChangedDimension(ServerPlayerEntity player) {
            if (!core_enabled) return;
            getOrAddPlayer(player);    // Freshen player object reference
        }

        public void onPlayerRespawn(ServerPlayerEntity player) {
            if (!core_enabled) return;
            getOrAddPlayer(player);    // Freshen player object reference
        }
    }

    private PlayerTracker playerTracker = null;

    private void registerPlayerLoginListener() {
        if (playerTracker == null) {
            playerTracker = new PlayerTracker();
            PlayerEvents.PLAYER_LOGGED_IN.register(player -> playerTracker.onPlayerLogin(player));
            PlayerEvents.PLAYER_LOGGED_OUT.register(player -> playerTracker.onPlayerLogout(player));
            PlayerEvents.PLAYER_CHANGED_DIMENSION.register(player -> playerTracker.onPlayerChangedDimension(player));
            PlayerEvents.PLAYER_RESPAWN.register(player -> playerTracker.onPlayerRespawn(player));
        }
    }

    public class WorldTracker {
        public void handleWorldLoad(MinecraftServer server, ServerWorld world) {
            if (!core_enabled) return;

            final FabricWorld fw = getWorld(world);
            // This event can be called from off server thread, so push processing there
            core.getServer().scheduleServerTask(new Runnable() {
                public void run() {
                    if (core.processWorldLoad(fw))    // Have core process load first - fire event listeners if good load after
                        core.listenerManager.processWorldEvent(DynmapListenerManager.EventType.WORLD_LOAD, fw);
                }
            }, 0);
        }

        public void handleWorldUnload(MinecraftServer server, ServerWorld world) {
            if (!core_enabled) return;

            final FabricWorld fw = getWorld(world);
            if (fw != null) {
                // This event can be called from off server thread, so push processing there
                core.getServer().scheduleServerTask(new Runnable() {
                    public void run() {
                        core.listenerManager.processWorldEvent(DynmapListenerManager.EventType.WORLD_UNLOAD, fw);
                        core.processWorldUnload(fw);
                    }
                }, 0);
                // Set world unloaded (needs to be immediate, since it may be invalid after event)
                fw.setWorldUnloaded();
                // Clean up tracker
                //WorldUpdateTracker wut = updateTrackers.remove(fw.getName());
                //if(wut != null) wut.world = null;
            }
        }

        public void handleChunkLoad(ServerWorld world, WorldChunk chunk) {
            if (!onchunkgenerate) return;

            if ((chunk != null) && (chunk.getStatus() == ChunkStatus.FULL)) {
                FabricWorld fw = getWorld(world, false);
                if (fw != null) {
                    addKnownChunk(fw, chunk.getPos());
                }
            }
        }

        public void handleChunkUnload(ServerWorld world, WorldChunk chunk) {
            if (!onchunkgenerate) return;

            if ((chunk != null) && (chunk.getStatus() == ChunkStatus.FULL)) {
                FabricWorld fw = getWorld(world, false);
                ChunkPos cp = chunk.getPos();
                if (fw != null) {
                    if (!checkIfKnownChunk(fw, cp)) {
                        int ymax = 0;
                        ChunkSection[] sections = chunk.getSectionArray();
                        for (int i = 0; i < sections.length; i++) {
                            if ((sections[i] != null) && (!sections[i].isEmpty())) {
                                ymax = 16 * (i + 1);
                            }
                        }
                        int x = cp.x << 4;
                        int z = cp.z << 4;
                        // If not empty AND not initial scan
                        if (ymax > 0) {
                            Log.info("New generated chunk detected at " + cp + " for " + fw.getName());
                            mapManager.touchVolume(fw.getName(), x, 0, z, x + 15, ymax, z + 16, "chunkgenerate");
                        }
                    }
                    removeKnownChunk(fw, cp);
                }
            }
        }

        public void handleChunkDataSave(ServerWorld world, Chunk chunk) {
            if (!onchunkgenerate) return;

            if ((chunk != null) && (chunk.getStatus() == ChunkStatus.FULL)) {
                FabricWorld fw = getWorld(world, false);
                ChunkPos cp = chunk.getPos();
                if (fw != null) {
                    if (!checkIfKnownChunk(fw, cp)) {
                        int ymax = 0;
                        ChunkSection[] sections = chunk.getSectionArray();
                        for (int i = 0; i < sections.length; i++) {
                            if ((sections[i] != null) && (!sections[i].isEmpty())) {
                                ymax = 16 * (i + 1);
                            }
                        }
                        int x = cp.x << 4;
                        int z = cp.z << 4;
                        // If not empty AND not initial scan
                        if (ymax > 0) {
                            mapManager.touchVolume(fw.getName(), x, 0, z, x + 15, ymax, z + 16, "chunkgenerate");
                        }
                        addKnownChunk(fw, cp);
                    }
                }
            }
        }

        public void handleBlockEvent(World world, BlockPos pos) {
            if (!core_enabled) return;
            if (!onblockchange) return;
            if (!(world instanceof ServerWorld)) return;

            BlockUpdateRec r = new BlockUpdateRec();
            r.w = world;
            FabricWorld fw = getWorld(world, false);
            if (fw == null) return;
            r.wid = fw.getName();
            r.x = pos.getX();
            r.y = pos.getY();
            r.z = pos.getZ();
            blockupdatequeue.add(r);
        }
    }

    private WorldTracker worldTracker = null;
    private boolean onblockchange = false;
    private boolean onchunkpopulate = false;
    private boolean onchunkgenerate = false;
    boolean onblockchange_with_id = false;

    private void registerEvents() {
        // To trigger rendering.
        onblockchange = core.isTrigger("blockupdate");
        onchunkpopulate = core.isTrigger("chunkpopulate");
        onchunkgenerate = core.isTrigger("chunkgenerate");
        onblockchange_with_id = core.isTrigger("blockupdate-with-id");
        if (onblockchange_with_id)
            onblockchange = true;
        if ((worldTracker == null) && (onblockchange || onchunkpopulate || onchunkgenerate)) {
            worldTracker = new WorldTracker();
            ServerWorldEvents.LOAD.register((server, world) -> worldTracker.handleWorldLoad(server, world));
            ServerWorldEvents.UNLOAD.register((server, world) -> worldTracker.handleWorldUnload(server, world));
            ServerChunkEvents.CHUNK_LOAD.register((world, chunk) -> worldTracker.handleChunkLoad(world, chunk));
            ServerChunkEvents.CHUNK_UNLOAD.register((world, chunk) -> worldTracker.handleChunkUnload(world, chunk));
            ChunkDataEvents.SAVE.register((world, chunk) -> worldTracker.handleChunkDataSave(world, chunk));
            BlockEvents.EVENT.register((world, pos) -> worldTracker.handleBlockEvent(world, pos));
        }
        // Prime the known full chunks
        if (onchunkgenerate && (server.getWorlds() != null)) {
            for (ServerWorld world : server.getWorlds()) {
                FabricWorld fw = getWorld(world);
                if (fw == null) continue;
                Long2ObjectLinkedOpenHashMap<ChunkHolder> chunks = ((ThreadedAnvilChunkStorageAccessor) world.getChunkManager().threadedAnvilChunkStorage).getChunkHolders();
                for (Map.Entry<Long, ChunkHolder> k : chunks.long2ObjectEntrySet()) {
                    long key = k.getKey();
                    ChunkHolder ch = k.getValue();
                    Chunk c = null;
                    try {
                        c = ch.getFuture().getNow(null);
                    } catch (Exception x) {
                    }
                    if (c == null) continue;
                    ChunkStatus cs = c.getStatus();
                    ChunkPos pos = ch.getPos();
                    if (cs == ChunkStatus.FULL) {    // Cooked?
                        // Add it as known
                        addKnownChunk(fw, pos);
                    }
                }
            }
        }
    }

    FabricWorld getWorldByName(String name) {
        return worlds.get(name);
    }

    FabricWorld getWorld(IWorld w) {
        return getWorld(w, true);
    }

    private FabricWorld getWorld(IWorld w, boolean add_if_not_found) {
        if (last_world == w) {
            return last_fworld;
        }
        String wname = FabricWorld.getWorldName(w);

        for (FabricWorld fw : worlds.values()) {
            if (fw.getRawName().equals(wname)) {
                last_world = w;
                last_fworld = fw;
                if (!fw.isLoaded()) {
                    fw.setWorldLoaded(w);
                }
                return fw;
            }
        }
        FabricWorld fw = null;
        if (add_if_not_found) {
            /* Add to list if not found */
            fw = new FabricWorld(plugin, w);
            worlds.put(fw.getName(), fw);
        }
        last_world = w;
        last_fworld = fw;
        return fw;
    }

    private void saveWorlds() {
        File f = new File(core.getDataFolder(), FabricWorld.SAVED_WORLDS_FILE);
        ConfigurationNode cn = new ConfigurationNode(f);
        ArrayList<HashMap<String, Object>> lst = new ArrayList<HashMap<String, Object>>();
        for (DynmapWorld fw : core.mapManager.getWorlds()) {
            HashMap<String, Object> vals = new HashMap<String, Object>();
            vals.put("name", fw.getRawName());
            vals.put("height", fw.worldheight);
            vals.put("sealevel", fw.sealevel);
            vals.put("nether", fw.isNether());
            vals.put("the_end", ((FabricWorld) fw).isTheEnd());
            vals.put("title", fw.getTitle());
            lst.add(vals);
        }
        cn.put("worlds", lst);
        cn.put("useSaveFolderAsName", useSaveFolder);
        cn.put("maxWorldHeight", FabricWorld.getMaxWorldHeight());

        cn.save();
    }

    private void loadWorlds() {
        File f = new File(core.getDataFolder(), FabricWorld.SAVED_WORLDS_FILE);
        if (f.canRead() == false) {
            useSaveFolder = true;
            return;
        }
        ConfigurationNode cn = new ConfigurationNode(f);
        cn.load();
        // If defined, use maxWorldHeight
        FabricWorld.setMaxWorldHeight(cn.getInteger("maxWorldHeight", 256));

        // If setting defined, use it
        if (cn.containsKey("useSaveFolderAsName")) {
            useSaveFolder = cn.getBoolean("useSaveFolderAsName", useSaveFolder);
        }
        List<Map<String, Object>> lst = cn.getMapList("worlds");
        if (lst == null) {
            Log.warning(String.format("Discarding bad %s", FabricWorld.SAVED_WORLDS_FILE));
            return;
        }

        for (Map<String, Object> world : lst) {
            try {
                String name = (String) world.get("name");
                int height = (Integer) world.get("height");
                int sealevel = (Integer) world.get("sealevel");
                boolean nether = (Boolean) world.get("nether");
                boolean theend = (Boolean) world.get("the_end");
                String title = (String) world.get("title");
                if (name != null) {
                    FabricWorld fw = new FabricWorld(plugin, name, height, sealevel, nether, theend, title);
                    fw.setWorldUnloaded();
                    core.processWorldLoad(fw);
                    worlds.put(fw.getName(), fw);
                }
            } catch (Exception x) {
                Log.warning(String.format("Unable to load saved worlds from %s", FabricWorld.SAVED_WORLDS_FILE));
                return;
            }
        }
    }
}


text:
Database version control, made easy!
=

**dbv.php** is a database version control web application featuring schema management, revision scripts, and more!

Check out the **[project website](http://dbv.vizuina.com)** for more details, features and documentation.

[![dbv.php](http://dbv.vizuina.com/img/screenshot-main.png)](http://dbv.vizuina.com)


text:
from glob import glob
import imutils
from os.path import relpath
import os
import numpy as np
import math
import cv2
import csv
import json
import sys

def getPatchPaths(path):
    return glob(path + "/**/*_patch_bw/") + glob(path + "/*_patch_bw/")

def loadImages(path, res):
    db = []
    print("Loading images...")

    with open(os.path.join(path, 'blender.csv'), 'w', newline='') as csvfile:
        fieldnames = ["filename", "file_size", "file_attributes", "region_count",
                      "region_id", "region_shape_attributes", "region_attributes"]
        writer = csv.DictWriter(
            csvfile, fieldnames=fieldnames, dialect='excel')
        writer.writeheader()

        for patch_folder in getPatchPaths(path):
            patch_folder_rel = str(relpath(patch_folder, path))
            mask_path = path + "/" + \
                        patch_folder_rel[0:-len("_patch_bw")] + "_patch_mask"
            for f in glob(patch_folder + "/*.png"):

                p = relpath(f, path)
                img = cv2.imread(f, cv2.IMREAD_GRAYSCALE)
                img = cv2.resize(img, (res["x"], res["y"]))

                # load mask file
                f_mask = mask_path + "/" + os.path.basename(p)
                if os.path.exists(f_mask):
                    img_mask = cv2.imread(f_mask, cv2.IMREAD_GRAYSCALE)
                    img_mask = cv2.resize(img_mask, (res["x"], res["y"]))
                elif "noball" in mask_path:
                    img_mask = np.zeros((res["x"], res["y"])).astype(np.uint8)
                else:
                    raise "Missing mask file for " + f

                # fit circle on img_mask
                _, contours, _ = cv2.findContours(img_mask, 1, 2)

                debug_img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)

                radius = 0
                x = res["x"] / 2
                y = res["y"] / 2
                region_count = 0
                # find largest circle (if existing)
                for cnt in contours:
                    (nx, ny), nradius = cv2.minEnclosingCircle(cnt)
                    if nradius >= radius:
                        x = nx
                        y = ny
                        radius = nradius + 1

                if radius > 0:
                    # draw detected circle into debug image
                    cv2.circle(debug_img, (int(x), int(y)),
                               int(radius), color=(0, 0, 255))

                    region = {"name": "circle", "cx": x, "cy": y, "r": radius}
                    atts = {"type": "ball"}
                    region_count = 1

                else:
                    radius = 0
                    x = 0.5
                    y = 0.5

                    region = {}
                    atts = {}

                writer.writerow(
                    {"filename": p, "file_attributes": "{}", "region_count": region_count,
                     "region_id": 0,
                     "region_shape_attributes": json.dumps(region),
                     "region_attributes": json.dumps(atts)})

                # cv2.namedWindow('image', cv2.WINDOW_NORMAL)
                # cv2.resizeWindow('image', 600, 600)
                # cv2.imshow("image", debug_img)
                # cv2.waitKey()

if __name__ == "__main__":
    if len(sys.argv) > 0:
        loadImages(sys.argv[1], res={"x": 16, "y": 16})


text:
package me.itzg.ignition.services;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.net.URI;

/**
 * @author Geoff Bourne
 * @since 6/16/2015
 */
@Component
@ConfigurationProperties(merge = false, prefix = "ignition.etcd")
public class EtcdProperties {
    private URI[] machines;

    public URI[] getMachines() {
        return machines;
    }

    public void setMachines(URI[] machines) {
        this.machines = machines;
    }
}


text:
from .basic_script import BasicScript

class Cooper(BasicScript):
    """Run the workflows once has been uploaded"""

    def get_arguments(self):
        """
        Get the arguments to configure current script
        :return: list
        """
        return [
            {
                'short': '-c',
                'long': '--cluster-id',
                'help': 'Provide a cluster id to work with, in case you don\'t provide one a list of available clusters will be shown to select one',
                'default': False
            },
            {
                'short': '-w',
                'long': '--wf-dir',
                'help': 'Folder where all the workflows files are present'
            },
            {
                'short': '-j',
                'long': '--job-file-name',
                'help': 'If set, we assume that it is the name of the workflow job configuration file, if not it will ask for the present ones',
                'default': False
            }
        ]

    def run(self, args, injector):
        """
        Run the component to run the workflows in the cluster
        :param args: Namespace
        :param injector: Injector
        """
        configuration = self.get_wf_configuration(args, injector)
        wf_compiled_dir = configuration.output_directory if configuration.output_directory else args.wf_dir
        cluster_id = configuration.cluster_id if 'cluster_id' in configuration else args.cluster_id

        properties_file = wf_compiled_dir + '/' + args.job_file_name if args.job_file_name != False else injector.get('interactive_properties_file').get(wf_compiled_dir)

        if properties_file:
            injector.get('logger').info(
                'Running {properties_file} in cluster {cluster_id}'.format(properties_file=properties_file,
                                                                           cluster_id=cluster_id))
            injector.get('emr_deploy').run_properties_file(properties_file, cluster_id)


text:
<!doctype html>

<meta charset="UTF-8">
<meta name="description" content="Daily Front-End Web Design and Development">
<meta name="keywords" content="HTML, CSS, Web Design, Front-End Development">
<meta name="author" content="Shakur Trammel">
<title>Daily Code 3</title>
<link rel="stylesheet" type="text/css" href="dailycode3.css">

Daily Code 3

December 28, 2016

Problem today: getting the header to display the text and getting the font-family displayed using @font-face.
Wasn't able to use the fonts I wanted to and the content of certain elements wouldn't display unless I set rules for the body element. Also, some weird stuff went down when I tried to put a paragraph element in the header element. I also forgot to "save as" and overwrote yesterday's DailyCode files. smh. Today's design had alot of issues!

I got the typefaces to display correctly in Chrome and Safari, but not in Firefox. I wonder why? I'm pretty sure it has something to do with the css I'm writing and/or the the font file format. The fonts wouldn't display properly until I changed the "font-family" value in the @font-face rule (no underscores in the name?). I was only able to use one cusotom font in Chrome. Good problems. I still have time before the day ends to fix them. My end goal is to get the same presentation in all three browsers.

A quick note on the typography: I really like Bebas Neue. Has a great vibe to it and instantly upgrades the design. It's like Impact but better. I wonder why?

Result: Design works across Chrome and Safari but custom font won't display in Firefox. I think that Firefox only supports WOFF and I only have the OTF version of the font.


text:
import { createStore, applyMiddleware, compose } from 'redux'
import thunk from 'redux-thunk';
import createLogger from 'redux-logger';
import rootReducer from '../reducers';
import { routerMiddleware } from 'react-router-redux';
import { browserHistory } from 'react-router';

const configureStore = preloadedState => {

  const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

  const middlewares = [ thunk, createLogger(), routerMiddleware(browserHistory) ]

  const store = createStore(
    rootReducer,
    preloadedState,
    composeEnhancers(applyMiddleware(...middlewares))
  );

  return store;
}

export default configureStore;


text:
<group>

Index

Prev

Next

IEDGE = VL_QUICKVIS(I, RATIO, KERNELSIZE, MAXDIST, MAXCUTS) creates an edge
stability image from a Quickshift segmentation. RATIO controls the tradeoff
between color consistency and spatial consistency (See VL_QUICKSEG) and
KERNELSIZE controls the bandwidth of the density estimator (See VL_QUICKSEG,
VL_QUICKSHIFT). MAXDIST is the maximum distance between neighbors which
increase the density.

VL_QUICKVIS takes at most MAXCUTS thresholds less than MAXDIST, forming at
most MAXCUTS segmentations. The edges between regions in each of these
segmentations are labeled in IEDGE, where the label corresponds to the
largest DIST which preserves the edge.

[IEDGE,DISTS] = VL_QUICKVIS(I, RATIO, KERNELSIZE, MAXDIST, MAXCUTS) also
returns the DIST thresholds that were chosen.

IEDGE = VL_QUICKVIS(I, RATIO, KERNELSIZE, DISTS) will use the DISTS
specified

[IEDGE,DISTS,MAP,GAPS] = VL_QUICKVIS(I, RATIO, KERNELSIZE, MAXDIST, MAXCUTS)
also returns the MAP and GAPS from VL_QUICKSHIFT.

See Also: VL_QUICKSHIFT(), VL_QUICKSEG(), VL_HELP().

</group>


text: A collection of classes used to make querying crypto-currency nodes easier.


text:
"""
DAG executors
"""
import logging

import networkx as nx
from tqdm.auto import tqdm
from dstools.pipeline.Table import BuildReport
from dstools.pipeline.executors.Executor import Executor
from dstools.pipeline.executors.LoggerHandler import LoggerHandler

class Serial(Executor):
    """Runs a DAG serially
    """
    TASKS_CAN_CREATE_CHILD_PROCESSES = True
    STOP_ON_EXCEPTION = True

    def __init__(self, logging_directory=None, logging_level=logging.INFO):
        self.logging_directory = logging_directory
        self.logging_level = logging_level
        self._logger = logging.getLogger(__name__)

    def __call__(self, dag, **kwargs):
        if self.logging_directory:
            logger_handler = LoggerHandler(dag_name=dag.name,
                                           directory=self.logging_directory,
                                           logging_level=self.logging_level)
            logger_handler.add()

        status_all = []

        g = dag._to_graph()
        pbar = tqdm(nx.algorithms.topological_sort(g), total=len(g))

        for t in pbar:
            pbar.set_description('Building task "{}"'.format(t.name))

            try:
                t.build(**kwargs)
            except Exception as e:
                if dag._on_task_failure:
                    dag._on_task_failure(t)

                raise e
            else:
                if dag._on_task_finish:
                    dag._on_task_finish(t)

            status_all.append(t.build_report)

        build_report = BuildReport(status_all)
        self._logger.info(' DAG report:\n{}'.format(repr(build_report)))

        for client in dag.clients.values():
            client.close()

        if self.logging_directory:
            logger_handler.remove()

        return build_report

    # __getstate__ and __setstate__ are needed to make this picklable

    def __getstate__(self):
        state = self.__dict__.copy()
        # _logger is not pickable, so we remove them and build
        # them again in __setstate__
        del state['_logger']
        return state

    def __setstate__(self, state):
        self.__dict__.update(state)
        self._logger = logging.getLogger(__name__)