/**
 * Selenium Plain Text To Selenese Parser v. 0.2
 * Copyright: <niklas.lindstrom@valtech.se>
 * License: BSD-style
 */

var COMMENT_RE = /\s*#([^"]*)$/; // hack to allow # in "":s
var LINE_COMMENT_RE = /^\s*#(.*)$/; // hack 2 to strip commented lines
var VALUE_RE = /(?:"([^"]+)"|(\S+))(.*)/;
var TRIPLE_BEGIN_RE = /^\s*"""(.*)/;
var TRIPLE_END_RE = /(.*)(""")(.*)/;

function ParsedResult(title, about, rows) {
    this.title = title;
    this.about = about;
    this.rows = rows;
}

function parsePlainText(fetchText, textUrl, text /*optional*/) {

    var text = text || fetchText(textUrl);
    var lines = text.split(/\r?\n/);

    var cols = [];
    var literal = null;

    var outrows = [];
    var title = null;
    var about = null;

    for (var j=0; j < lines.length; j++) {
        var line = lines[j];

        // build multiline literal (which may end here)
        if (literal != null) {
            line = line.replace(TRIPLE_END_RE, '$3');
            if (RegExp.$2) {
                cols.push(literal + "\n" + RegExp.$1);
                literal = null;
            } else {
                literal += "\n" + line;
                continue;
            }
        }

        // strip comments
        line = line.replace(COMMENT_RE, '');
        line = line.replace(LINE_COMMENT_RE, '');

        // skip empty lines
        if (line != '') {

            // handle metadata
            if (line.match(/^\s*title:(.*)/)) {
                title = RegExp.$1;
            } else if (line.match(/^\s*about:(.*)/)) {
                about = RegExp.$1;

            // handle include directive
            } else if (line.match(/^\s*@include\s+(.+)/)) {
                outrows = outrows.concat(parsePlainText(fetchText, RegExp.$1).rows);

            } else {
                // parse cell values (max three)
                while(cols.length < 3) {
                    if (line.match(TRIPLE_BEGIN_RE)) {
                        literal = RegExp.$1;
                        literal.match(TRIPLE_END_RE);
                        if (RegExp.$2) {
                            literal = literal.replace(TRIPLE_END_RE, "$1");
                            line = RegExp.$3;
                            cols.push(literal);
                            literal = null;
                        } else {
                            break; // unfinished multiline literal has begun
                        }
                    } else {
                        if (line.match(VALUE_RE)) {
                            cols.push(RegExp.$1 + RegExp.$2);
                            line = RegExp.$3;
                        } else break;
                    }
                }
            }

            if (literal != null)  {
                continue; // unfinished multiline; don't complete with empty cells
            }

        }

        // if at least one cell value
        if (cols.length > 0) {
            // complete with empty cells
            for (var i=cols.length; i < 3; i++) {
                cols[i] = '';
            }
            outrows.push('<tr><td>'+cols[0]+'</td><td>'+cols[1]+'</td><td>'+cols[2]+'</td></tr>');
            cols = [];
        }
    }
    return new ParsedResult(title, about, outrows);
}

