package gherkin;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

import static gherkin.StringUtils.ltrim;

public class GherkinLine implements IGherkinLine {
    private final String lineText;
    private final String trimmedLineText;

    public GherkinLine(String lineText) {
        this.lineText = lineText;
        this.trimmedLineText = ltrim(lineText);
    }

    @Override
    public Integer indent() {
        return lineText.length() - trimmedLineText.length();
    }

    @Override
    public void detach() {

    }

    @Override
    public String getLineText(int indentToRemove) {
        if (indentToRemove < 0 || indentToRemove > indent())
            return trimmedLineText;
        return lineText.substring(indentToRemove);
    }

    @Override
    public boolean isEmpty() {
        return trimmedLineText.length() == 0;
    }

    @Override
    public boolean startsWith(String prefix) {
        return trimmedLineText.startsWith(prefix);
    }

    @Override
    public String getRestTrimmed(int length) {
        return trimmedLineText.substring(length).trim();
    }

    @Override
    public List<GherkinLineSpan> getTags() {
        return getSpans("\\s+");
    }

    @Override
    public boolean startsWithTitleKeyword(String text) {
        int textLength = text.length();
        return trimmedLineText.length() > textLength &&
                trimmedLineText.startsWith(text) &&
                trimmedLineText.substring(textLength, textLength + GherkinLanguageConstants.TITLE_KEYWORD_SEPARATOR.length())
                        .equals(GherkinLanguageConstants.TITLE_KEYWORD_SEPARATOR);
        // TODO aslak: extract startsWithFrom method for clarity
    }

    @Override
    public List<GherkinLineSpan> getTableCells() {
        return getSpans("\\s*\\|\\s*");
    }

    private List<GherkinLineSpan> getSpans(String delimiter) {
        List<GherkinLineSpan> lineSpans = new ArrayList<GherkinLineSpan>();
        Scanner scanner = new Scanner(trimmedLineText).useDelimiter(delimiter);
        while (scanner.hasNext()) {
            String cell = scanner.next();
            int column = scanner.match().start() + indent() + 1;
            lineSpans.add(new GherkinLineSpan(column, cell));
        }
        return lineSpans;
    }
}

@@ -1791,38 +1791,1398 @@
     
-return getSpans(%22%5C%5Cs*%5C%5C%7C%5C%5Cs*%22)
+List%3CGherkinLineSpan%3E lineSpans = new ArrayList%3CGherkinLineSpan%3E();%0A        StringBuilder cell = new StringBuilder();%0A        boolean beforeFirst = true;%0A        int startCol = 0;%0A        for (int col = 0; col %3C trimmedLineText.length(); col++) %7B%0A            char c = trimmedLineText.charAt(col);%0A            if (c == '%7C') %7B%0A                if (beforeFirst) %7B%0A                    // Skip the first empty span%0A                    beforeFirst = false;%0A                %7D else %7B%0A                    int contentStart = 0;%0A                    while (contentStart %3C cell.length() && Character.isWhitespace(cell.charAt(contentStart))) %7B%0A                        contentStart++;%0A                    %7D%0A                    if (contentStart == cell.length()) %7B%0A                        contentStart = 0;%0A                    %7D%0A                    lineSpans.add(new GherkinLineSpan(indent() + startCol + contentStart + 2, cell.toString().trim()));%0A                    startCol = col;%0A                %7D%0A                cell = new StringBuilder();%0A            %7D else if (c == '%5C%5C') %7B%0A                col++;%0A                c = trimmedLineText.charAt(col);%0A                if (c == 'n') %7B%0A                    cell.append('%5Cn');%0A                %7D else %7B%0A                    cell.append(c);%0A                %7D%0A            %7D else %7B%0A                cell.append(c);%0A            %7D%0A        %7D%0A%0A        return lineSpans
 ;%0A  

handle escaping in table cells