text: 'use strict';
  
  var insertSVGTemplateAssign = require('./insert-svg-template-assign');
  
  function render (tree, state) {
      var y, i, ilen;
  
      state.xmax = Math.max(state.xmax, state.x);
      y = state.y;
      ilen = tree.length;
      for (i = 1; i < ilen; i++) {
          if (Object.prototype.toString.call(tree[i]) === '[object Array]') {
              state = render(tree[i], {x: (state.x + 1), y: state.y, xmax: state.xmax});
          } else {
              tree[i] = {name:tree[i], x: (state.x + 1), y: state.y};
              state.y += 2;
          }
      }
      tree[0] = {name: tree[0], x: state.x, y: Math.round((y + (state.y - 2)) / 2)};
      state.x--;
      return state;
  }
  
  function draw_body (type, ymin, ymax) {
      var e,
          iecs,
          circle = ' M 4,0 C 4,1.1 3.1,2 2,2 0.9,2 0,1.1 0,0 c 0,-1.1 0.9,-2 2,-2 1.1,0 2,0.9 2,2 z',
          gates = {
              '~':  'M -11,-6 -11,6 0,0 z m -5,6 5,0' + circle,
              '=':  'M -11,-6 -11,6 0,0 z m -5,6 5,0',
              '&':  'm -16,-10 5,0 c 6,0 11,4 11,10 0,6 -5,10 -11,10 l -5,0 z',
              '~&': 'm -16,-10 5,0 c 6,0 11,4 11,10 0,6 -5,10 -11,10 l -5,0 z' + circle,
              '|':  'm -18,-10 4,0 c 6,0 12,5 14,10 -2,5 -8,10 -14,10 l -4,0 c 2.5,-5 2.5,-15 0,-20 z',
              '~|': 'm -18,-10 4,0 c 6,0 12,5 14,10 -2,5 -8,10 -14,10 l -4,0 c 2.5,-5 2.5,-15 0,-20 z' + circle,
              '^':  'm -21,-10 c 1,3 2,6 2,10 m 0,0 c 0,4 -1,7 -2,10 m 3,-20 4,0 c 6,0 12,5 14,10 -2,5 -8,10 -14,10 l -4,0 c 1,-3 2,-6 2,-10 0,-4 -1,-7 -2,-10 z',
              '~^': 'm -21,-10 c 1,3 2,6 2,10 m 0,0 c 0,4 -1,7 -2,10 m 3,-20 4,0 c 6,0 12,5 14,10 -2,5 -8,10 -14,10 l -4,0 c 1,-3 2,-6 2,-10 0,-4 -1,-7 -2,-10 z' + circle,
              '+':  'm -8,5 0,-10 m -5,5 10,0 m 3,0 c 0,4.418278 -3.581722,8 -8,8 -4.418278,0 -8,-3.581722 -8,-8 0,-4.418278 3.581722,-8 8,-8 4.418278,0 8,3.581722 8,8 z',
              '*':  'm -4,4 -8,-8 m 0,8 8,-8 m 4,4 c 0,4.418278 -3.581722,8 -8,8 -4.418278,0 -8,-3.581722 -8,-8 0,-4.418278 3.581722,-8 8,-8 4.418278,0 8,3.581722 8,8 z'
          },
          iec = {
              BUF: 1, INV: 1, AND: '&',  NAND: '&',
              OR: '\u22651', NOR: '\u22651', XOR: '=1', XNOR: '=1', box: ''
          },
          circled = { INV: 1, NAND: 1, NOR: 1, XNOR: 1 };
  
      if (ymax === ymin) {
          ymax = 4; ymin = -4;
      }
      e = gates[type];
      iecs = iec[type];
      if (e) {
          return ['path', {class:'gate', d: e}];
      } else {
          if (iecs) {
              return [
                  'g', [
                      'path', {
                          class:'gate',
                          d: 'm -16,' + (ymin - 3) + ' 16,0 0,' + (ymax - ymin + 6) + ' -16,0 z' + (circled[type] ? circle : '')
                      }], [
                      'text', [
                          'tspan', {x: '-14', y: '4', class: 'wirename'}, iecs + ''
                      ]
                  ]
              ];
          } else {
              return ['text', ['tspan', {x: '-14', y: '4', class: 'wirename'}, type + '']];
          }
      }
  }
  
  function draw_gate (spec) { // ['type', [x,y], [x,y] ... ]
      var i,
          ret = ['g'],
          ys = [],
          ymin,
          ymax,
          ilen = spec.length;
  
      for (i = 2; i < ilen; i++) {
          ys.push(spec[i][1]);
      }
  
      ymin = Math.min.apply(null, ys);
      ymax = Math.max.apply(null, ys);
  
      ret.push(
          ['g',
              {transform:'translate(16,0)'},
              ['path', {
                  d: 'M  ' + spec[2][0] + ',' + ymin + ' ' + spec[2][0] + ',' + ymax,
                  class: 'wire'
              }]
          ]
      );
  
      for (i = 2; i < ilen; i++) {
          ret.push(
              ['g',
                  ['path',
                      {
                          d: 'm  ' + spec[i][0] + ',' + spec[i][1] + ' 16,0',
                          class: 'wire'
                      }
                  ]
              ]
          );
      }
      ret.push(
          ['g', { transform: 'translate(' + spec[1][0] + ',' + spec[1][1] + ')' },
              ['title', spec[0]],
              draw_body(spec[0], ymin - spec[1][1], ymax - spec[1][1])
          ]
      );
      return ret;
  }
  
  function draw_boxes (tree, xmax) {
      var ret = ['g'], i, ilen, fx, fy, fname, spec = [];
      if (Object.prototype.toString.call(tree) === '[object Array]') {
          ilen = tree.length;
          spec.push(tree[0].name);
          spec.push([32 * (xmax - tree[0].x), 8 * tree[0].y]);
          for (i = 1; i < ilen; i++) {
              if (Object.prototype.toString.call(tree[i]) === '[object Array]') {
                  spec.push([32 * (xmax - tree[i][0].x), 8 * tree[i][0].y]);
              } else {
                  spec.push([32 * (xmax - tree[i].x), 8 * tree[i].y]);
              }
          }
          ret.push(draw_gate(spec));
          for (i = 1; i < ilen; i++) {
              ret.push(draw_boxes(tree[i], xmax));
          }
      } else {
          fname = tree.name;
          fx = 32 * (xmax - tree.x);
          fy = 8 * tree.y;
          ret.push(
              ['g', { transform: 'translate(' + fx + ',' + fy + ')'},
                  ['title', fname],
                  ['path', {d:'M 2,0 a 2,2 0 1 1 -4,0 2,2 0 1 1 4,0 z'}],
                  ['text',
                      ['tspan', {
                          x:'-4', y:'4',
                          class:'pinname'},
                      fname
                      ]
                  ]
              ]
          );
      }
      return ret;
  }
  
  function renderAssign (index, source) {
      var tree,
          state,
          xmax,
          svg = ['g'],
          grid = ['g'],
          // svgcontent,
          width,
          height,
          i,
          ilen,
          j,
          jlen;
  
      ilen = source.assign.length;
      state = { x: 0, y: 2, xmax: 0 };
      tree = source.assign;
      for (i = 0; i < ilen; i++) {
          state = render(tree[i], state);
          state.x++;
      }
      xmax = state.xmax + 3;
  
      for (i = 0; i < ilen; i++) {
          svg.push(draw_boxes(tree[i], xmax));
      }
      width  = 32 * (xmax + 1) + 1;
      height = 8 * (state.y + 1) - 7;
      ilen = 4 * (xmax + 1);
      jlen = state.y + 1;
      for (i = 0; i <= ilen; i++) {
          for (j = 0; j <= jlen; j++) {
              grid.push(['rect', {
                  height: 1,
                  width: 1,
                  x: (i * 8 - 0.5),
                  y: (j * 8 - 0.5),
                  class: 'grid'
              }]);
          }
      }
      return ['svg', {
          id: 'svgcontent_' + index,
          viewBox: '0 0 ' + width + ' ' + height,
          width: width,
          height: height
      },
      insertSVGTemplateAssign(),
      ['g', {transform:'translate(0.5, 0.5)'}, grid, svg]
      ];
  }
  
  module.exports = renderAssign;
  