package org.jetbrains.plugins.textmate.regex;

import com.google.common.base.Preconditions;
import com.intellij.openapi.util.TextRange;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.joni.Region;

import java.util.Arrays;

public class MatchData {
  public static final MatchData NOT_MATCHED = new MatchData(false, TextRange.EMPTY_ARRAY);

  private final boolean matched;
  @NotNull
  private final TextRange[] offsets;

  private MatchData(boolean matched, @NotNull TextRange[] offsets) {
    this.matched = matched;
    this.offsets = offsets;
  }

  public static MatchData fromRegion(@Nullable Region matchedRegion) {
    if (matchedRegion != null) {
      TextRange[] offsets = new TextRange[matchedRegion.numRegs];
      for (int i = 0; i < matchedRegion.numRegs; i++) {
        offsets[i] = TextRange.create(Math.max(matchedRegion.beg[i], 0), Math.max(matchedRegion.end[i], 0));
      }
      return new MatchData(true, offsets);
    }
    return NOT_MATCHED;
  }

  public int count() {
    return offsets.length;
  }

  public TextRange byteOffset() {
    return byteOffset(0);
  }

  @NotNull
  public TextRange byteOffset(int group) {
    Preconditions.checkElementIndex(group, offsets.length);
    return offsets[group];
  }

  public TextRange charOffset(byte[] stringBytes) {
    return charOffset(stringBytes, 0);
  }

  @NotNull
  public TextRange charOffset(byte[] stringBytes, int group) {
    return RegexUtil.charRangeByByteRange(stringBytes, byteOffset(group));
  }

  public boolean matched() {
    return matched;
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;

    MatchData matchData = (MatchData)o;

    if (matched != matchData.matched) return false;
    if (!Arrays.equals(offsets, matchData.offsets)) return false;

    return true;
  }

  @Override
  public int hashCode() {
    return 31 * (matched ? 1 : 0) + Arrays.hashCode(offsets);
  }

  @Override
  public String toString() {
    return "{ matched=" + matched + ", offsets=" + Arrays.toString(offsets) + '}';
  }
}

@@ -129,16 +129,52 @@
 tRange;%0A
+import com.intellij.util.ArrayUtil;%0A
 import o
@@ -397,24 +397,28 @@
 se, 
-TextRange
+ArrayUtil
 .EMPTY_
+INT_
 ARRA
@@ -482,25 +482,19 @@
 e final 
-TextRange
+int
 %5B%5D offse
@@ -544,25 +544,19 @@
 NotNull 
-TextRange
+int
 %5B%5D offse
@@ -732,25 +732,19 @@
 %7B%0A      
-TextRange
+int
 %5B%5D offse
@@ -752,25 +752,19 @@
 s = new 
-TextRange
+int
 %5Bmatched
@@ -777,16 +777,20 @@
 .numRegs
+ * 2
 %5D;%0A     
@@ -852,72 +852,130 @@
     
-offsets%5Bi%5D = TextRange.create(Math.max(matchedRegion.beg%5Bi%5D, 0),
+int startIndex = i * 2;%0A        offsets%5BstartIndex%5D = Math.max(matchedRegion.beg%5Bi%5D, 0);%0A        offsets%5BstartIndex + 1%5D =
  Mat
@@ -1004,17 +1004,16 @@
 d%5Bi%5D, 0)
-)
 ;%0A      
@@ -1140,16 +1140,20 @@
 s.length
+ / 2
 ;%0A  %7D%0A%0A 
@@ -1266,24 +1266,58 @@
 nt group) %7B%0A
+    int endIndex = group * 2 + 1;%0A
     Precondi
@@ -1340,21 +1340,24 @@
 ntIndex(
-group
+endIndex
 , offset
@@ -1382,22 +1382,66 @@
 urn 
-offsets%5Bgroup%5D
+TextRange.create(offsets%5BendIndex - 1%5D, offsets%5BendIndex%5D)
 ;%0A  

use array of ints instead of TextRanges