/*
 * Copyright 2000-2013 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.intellij.spellchecker.inspections;

import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicatorProvider;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.Consumer;
import com.intellij.util.SmartList;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.text.CharacterIterator;
import java.text.StringCharacterIterator;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public abstract class BaseSplitter implements Splitter {

  static final Logger LOG = Logger.getInstance("#com.intellij.spellchecker.inspections.BaseSplitter");

  public static final int MIN_RANGE_LENGTH = 3;


  protected static void addWord(@NotNull Consumer<TextRange> consumer, boolean ignore, @Nullable TextRange found) {
    if (found == null || ignore) {
      return;
    }
    boolean tooShort = (found.getEndOffset() - found.getStartOffset()) <= MIN_RANGE_LENGTH;
    if (tooShort) {
      return;
    }
    consumer.consume(found);
  }


  protected static boolean isAllWordsAreUpperCased(@NotNull String text, @NotNull List<TextRange> words) {
    for (TextRange word : words) {
      CharacterIterator it = new StringCharacterIterator(text, word.getStartOffset(), word.getEndOffset(), word.getStartOffset());
      for (char c = it.first(); c != CharacterIterator.DONE; c = it.next()) {
        if (!Character.isUpperCase(c)) {
          return false;
        }
      }
    }
    return true;

  }

  protected static boolean containsShortWord(@NotNull List<TextRange> words) {
    for (TextRange word : words) {
      if (word.getLength() < MIN_RANGE_LENGTH) {
        return true;
      }
    }
    return false;
  }

  @NotNull
  protected static TextRange matcherRange(@NotNull TextRange range, @NotNull Matcher matcher) {
    return subRange(range, matcher.start(), matcher.end());
  }

  @NotNull
  protected static TextRange matcherRange(@NotNull TextRange range, @NotNull Matcher matcher, int group) {
    return subRange(range, matcher.start(group), matcher.end(group));
  }

  @NotNull
  protected static TextRange subRange(@NotNull TextRange range, int start, int end) {
    return TextRange.from(range.getStartOffset() + start, end - start);
  }

  protected static boolean badSize(int from, int till) {
    int l = till - from;
    return l <= MIN_RANGE_LENGTH;
  }

  @NotNull
  static protected List<TextRange> excludeByPattern(String text, TextRange range, @NotNull Pattern toExclude, int groupToInclude) {
    List<TextRange> toCheck = new SmartList<TextRange>();
    int from = range.getStartOffset();
    int till;
    boolean addLast = true;
    Matcher matcher = toExclude.matcher(StringUtil.newBombedCharSequence(range.substring(text), 500));
    try {
      while (matcher.find()) {
        checkCancelled();
        TextRange found = matcherRange(range, matcher);
        till = found.getStartOffset();
        if (range.getEndOffset() - found.getEndOffset() < MIN_RANGE_LENGTH) {
          addLast = false;
        }
        if (!badSize(from, till)) {
          toCheck.add(new TextRange(from, till));
        }
        if (groupToInclude > 0) {
          TextRange contentFound = matcherRange(range, matcher, groupToInclude);
          if (badSize(contentFound.getEndOffset(), contentFound.getStartOffset())) {
            toCheck.add(TextRange.create(contentFound));
          }
        }
        from = found.getEndOffset();
      }
      till = range.getEndOffset();
      if (badSize(from, till)) {
        return toCheck;
      }
      if (addLast) {
        toCheck.add(new TextRange(from, till));
      }
      return toCheck;
    }
    catch (ProcessCanceledException e) {
      //LOG.warn("Matching took too long: >>>" + range.substring(text) + "<<< " + toExclude);
      return Collections.singletonList(range);
      //return Collections.emptyList();
    }
  }

  public static void checkCancelled() {
    ProgressIndicatorProvider.checkCanceled();
  }


}
