/*
 * 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.openapi.editor.impl.softwrap;

import com.intellij.openapi.editor.FoldRegion;
import com.intellij.openapi.editor.SoftWrap;
import com.intellij.openapi.editor.impl.AbstractEditorTest;
import com.intellij.testFramework.EditorTestUtil;
import com.intellij.testFramework.TestFileType;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class SoftWrapTest extends AbstractEditorTest {

  public void testCollapsedRegionWithLongPlaceholderAtLineStart1() throws IOException {
    doTestSoftWraps(10, "<fold text='veryVeryVeryLongPlaceholder'>foo</fold>");
  }

  public void testCollapsedRegionWithLongPlaceholderAtLineStart2() throws IOException {
    doTestSoftWraps(10, "<fold text='veryVeryVeryLongPlaceholder'>foo</fold><wrap>bar");
  }

  public void testCollapsedRegionWithLongPlaceholderAtLineStart3() throws IOException {
    doTestSoftWraps(10, "<fold text='veryVeryVeryLongPlaceholder'>foo</fold>\nvery long <wrap>text");
  }

  private static final String TAGS_PATTERN = "(<fold(\\stext=\'([^\']*)\')?>)|(</fold>)|<wrap>";

  private void doTestSoftWraps(int wrapWidth, String text) throws IOException {
    List<MyFoldRegion> foldRegions = new ArrayList<MyFoldRegion>();
    List<Integer> wrapPositions = new ArrayList<Integer>();
    int foldInsertPosition = 0;
    int pos = 0;
    int docPos = 0;
    Matcher matcher = Pattern.compile(TAGS_PATTERN).matcher(text);
    StringBuilder cleanedText = new StringBuilder();
    while(matcher.find()) {
      cleanedText.append(text.substring(pos, matcher.start()));
      docPos += matcher.start() - pos;
      pos = matcher.end();
      if (matcher.group(1) != null) {       // <fold>
        foldRegions.add(foldInsertPosition++, new MyFoldRegion(docPos, matcher.group(3), matcher.group(2) != null));
      }
      else if (matcher.group(4) != null) {  // </fold>
        assertTrue("Misplaced closing fold marker tag: " + text, foldInsertPosition > 0);
        foldRegions.get(--foldInsertPosition).endPos = docPos;
      }
      else {                                // <wrap>
        wrapPositions.add(docPos);
      }
    }
    assertTrue("Missing closing fold marker tag: " + text, foldInsertPosition == 0);
    cleanedText.append(text.substring(pos));

    init(cleanedText.toString(), TestFileType.TEXT);

    for (MyFoldRegion region : foldRegions) {
      FoldRegion r = addFoldRegion(region.startPos, region.endPos, region.placeholder);
      if (region.collapse) {
        toggleFoldRegionState(r, false);
      }
    }

    EditorTestUtil.configureSoftWraps(myEditor, wrapWidth);

    List<Integer> actualWrapPositions = new ArrayList<Integer>();
    for (SoftWrap wrap : myEditor.getSoftWrapModel().getSoftWrapsForRange(0, myEditor.getDocument().getTextLength())) {
      actualWrapPositions.add(wrap.getStart());
    }
    assertEquals("Wrong wrap positions", wrapPositions, actualWrapPositions);
  }

  private static class MyFoldRegion {
    private final int startPos;
    private int endPos;
    private final String placeholder;
    private final boolean collapse;

    private MyFoldRegion(int pos, String placeholder, boolean collapse) {
      this.startPos = pos;
      this.placeholder = placeholder;
      this.collapse = collapse;
    }
  }
}
