"use strict";

var fs = require("fs");
var path = require("path");
var util = require("util");
var marked = require("marked");

var refdir = path.dirname(__dirname);
var tmpl = fs.readFileSync(path.join(refdir, "template.html")).toString()
var md = fs.readFileSync(process.argv[2]).toString();

function escape(str) {
  return str
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#39;');
}

function MyRenderer() {
  this.cjsUsedAnchors = {};
}

util.inherits(MyRenderer, marked.Renderer);

MyRenderer.prototype.code = function(code, lang) {
  if (lang) return marked.Renderer.prototype.code(code, lang);
  // console.log("code='" + code + "'")
  var lines = code.split("\n");
  var n = lines.length, i;
  if (lines[n-1] === "") --n;
  var cls = {
    "T ": "txt",
    "J ": "js",
    "> ": "code",
    "< ": "result",
    "~ ": "regexp",
    "* ": "output",
    "D ": "draw2d",
    "- ": "pragma",
  };
  var bcls = {
    "T ": "txtblock",
    "J ": "jsblock",
    "> ": "codeblock",
    "< ": "codeblock",
    "* ": "codeblock",
    "D ": "codeblock",
    "~ ": "codeblock",
  };
  var outer = 'block', prevmark = '', res = '';
  for (i = 0; i < n; ++i) {
    var mark = lines[i].substr(0, 2);
    outer = bcls[mark] || outer;
    if (mark !== prevmark) {
      if (i === 0)
        res += '<pre class="fst ';
      else
        res += '</pre><pre class="';
      res += cls[mark] + '">';
      prevmark = mark;
    }
    else
      res += '\n';
    res += escape(lines[i].substr(2));
  }
  return '<div class="' + outer + '">' + res + '</pre></div>';
};

MyRenderer.prototype.heading = function(text, level, raw) {
  var id = null;
  var match;
  if (!id && (match = /(\w+)\(([^)]*)\)/.exec(raw))) {
    // normal named functions
    var arity = 0;
    if (match[2] !== "")
      arity = match[2].split(",").length;
    id = match[1] + "$" + arity;
  }
  if (!id && (match = /`‹\w*›\s*(\S+)\s*‹\w*›`/.exec(raw))) {
    // infix operators
    id = "$" + match[1].replace(/./g, function(char) {
      return "u" + char.charCodeAt(0).toString(16);
    });
  }
  if (!id && (match = /`([^`]*)`/.exec(raw))) {
    // other code constructs
    match = match[1];
    id = match
      .replace(/\s+/g, "")
      .replace(/_/g, "\\$u5f")
      .replace(/‹[^‹›]*›/g, "_")
      .replace(/\W/g, function(char) {
        return "$u" + char.charCodeAt(0).toString(16);
      });
  }
  if (!id && (match = /([\w.]+)\s*=.*‹/.exec(raw))) {
    // Named settings with structure specification
    id = match[1];
  }
  if (!id && (match = /\u2039/.exec(raw))) {
    throw Error("Don't know how to create an ID for: " + raw);
  }
  if (!id) {
    // Final fallback
    id = raw.toLowerCase().replace(/[^\w.]+/g, '-');
  }
  if (this.cjsUsedAnchors.hasOwnProperty(id)) {
    var idx = 9, id2;
    do {
      ++idx;
      id2 = id + idx.toString(36); // append a, b, …
    } while (this.cjsUsedAnchors.hasOwnProperty(id2));
    id = id2;
  }
  //console.log(id);
  this.cjsUsedAnchors[id] = raw;
  return '<h' + level + ' id="' + id + '">' + text +
    '<a class="hlink" href="#' + id + '"></a></h' + level + '>\n';
};

function makeOpts() {
  return {
    renderer: new MyRenderer()
  };
}

marked(md, makeOpts(), function(err, html) {
    if (err) throw err;
    html = tmpl.replace(/<div id="content"><\/div>/, html);
    fs.writeFileSync(process.argv[3], html);
});

@@ -1998,22 +1998,16 @@
     id =
- %22$%22 +
  match%5B1
@@ -2053,17 +2053,17 @@
 return %22
-u
+$
 %22 + char
@@ -2085,24 +2085,30 @@
 toString(16)
+ + %22u%22
 ;%0A    %7D);%0A  
@@ -2270,17 +2270,18 @@
 ce(/
-_
+%5C$
 /g, %22%5C%5C$
 u5f%22
@@ -2280,11 +2280,42 @@
 %22%5C%5C$
-u
+24u%22)%0A      .replace(/_/g, %22%5C%5C$
 5f
+u
 %22)%0A 
@@ -2402,17 +2402,16 @@
 eturn %22$
-u
 %22 + char
@@ -2437,16 +2437,22 @@
 ring(16)
+ + %22u%22
 ;%0A      

Put u after char code