;(function(global) {
  "use strict";

var Rpd = global.Rpd;
if (typeof Rpd === "undefined" && typeof require !== "undefined") {
    Rpd = require('rpd');
}

function nodeToString ( node ) {
    var tmpNode = document.createElement( "div" );
    tmpNode.appendChild( node.cloneNode( true ) );
    var str = tmpNode.innerHTML;
    tmpNode = node = null; // prevent memory leaks in IE
    return str;
}

Rpd.style('quartz', 'html', function(config) {

var lastCanvas;

var inletToConnector = {},
    outletToConnector = {};

function getPos(elm) { var bounds = elm.getBoundingClientRect();
                       return { x: bounds.left, y: bounds.top } };

return {

    edgePadding: { horizontal: 30, vertical: 20 },
    boxPadding:  { horizontal: 20, vertical: 30 },

    createCanvas: function(patch, parent) {
        return {
            element: d3.select(document.createElement('div'))
                       .classed('rpd-patch', true).node()
        };
    },

    createNode: function(node, render, description, icon) {

        var nodeElm = d3.select(document.createElement('table'))
                        .attr('class', 'rpd-node');

        // node header: node title and remove button
        nodeElm.append('thead').attr('class', 'rpd-title')
                               .classed('rpd-drag-handle', true) // a mark for renderer
               // remove button
               .call(function(thead) {
                   thead.append('tr').attr('class', 'rpd-remove-button')
                        .append('th')/*.attr('colspan', '3')*/.text('x');
               })
               // node name, and type, if requested
               .call(function(thead) {
                    thead.append('tr').attr('class', 'rpd-header')
                         .append('th').attr('colspan', 3)
                         .call(function(th) {
                             if (config.showTypes) th.append('span').attr('class', 'rpd-type').text(node.type);
                             if (icon) th.append('span').attr('class', 'rpd-icon').text(icon);
                             th.append('span').attr('class', 'rpd-name').text(node.def.title || node.type);
                             // add description to be shown on hover
                             th.attr('title', description ? (description + ' (' + node.type + ')') : node.type);
                         });

               });

        // node content
        nodeElm.append('tbody').attr('class', 'rpd-content')
               .call(function(tbody) {
                   tbody.append('tr')
                        // inlets placeholder
                        .call(function(tr) {
                            tr.append('td').attr('class', 'rpd-inlets')
                              .append('table')
                              .append('tbody')
                              .append('div').attr('class', 'rpd-inlets-target'); // -> node/add-inlet
                        })
                        // node body
                        .call(function(tr) {
                            tr.append('td').attr('class', 'rpd-body')
                              .append('table')
                              .append('tbody').append('tr').append('td')
                              .append('div').attr('class', 'rpd-process-target'); // -> node/process
                        })
                        // outlets placeholder
                        .call(function(tr) {
                            tr.append('td').attr('class', 'rpd-outlets')
                              .append('table')
                              .append('tbody')
                              .append('div').attr('class', 'rpd-outlets-target'); // -> node/add-outlet
                        })
               });

        return {
            element: nodeElm.node(),
            size: render.size ? { width: render.size.width || 70, height: render.size.height || 30 }
                              : { width: 70, height: 30 }
        };

    },

    createInlet: function(inlet, render) {
        var inletElm = d3.select(document.createElement('tr'))
                         .attr('class', 'rpd-inlet')
                         .call(function(tr) {
                             tr.append('td').attr('class', 'rpd-connector');
                             tr.append('td').attr('class', 'rpd-value-holder')
                                            .append('span').attr('class', 'rpd-value');
                             tr.append('td').attr('class', 'rpd-name').text(inlet.def.label || inlet.alias);
                             if (config.showTypes) tr.append('td').attr('class', 'rpd-type').text(inlet.type);
                         });
        inletToConnector[inlet.id] = inletElm.select('.rpd-connector');
        return { element: inletElm.node() };
    },

    createOutlet: function(outlet, render, list) {
        if(outlet.parent) {
            var trClass = outlet.parent.split(' ').join(outlet.node.id + ' ') + outlet.node.id
            ;
        }

        var outletElm = d3.select(document.createElement('tr'))
                          .attr('class', 'rpd-outlet ' + trClass)
                          .call(function(tr) {
                              if(list) {
                                  tr.html(nodeToString(list));
                                  tr.append('td').attr('class', 'rpd-connector');
                                  tr.append('td').attr('class', 'rpd-value');
                                  if (config.showTypes) tr.append('td').attr('class', 'rpd-type').text(outlet.type);
                              } else {
                                  if(outlet.space) {
                                      if(outlet.showConnector) {
                                          tr.append('td').attr('class', 'rpd-connector');
                                      } else {
                                          var td = tr.append('td').attr('class', 'rpd-connector disable');
                                          var id = outlet.parent.split(' ');
                                          var check = td.append('input').attr('type', 'checkbox').attr('id', id[id.length - 1] + outlet.node.id)
                                          check.on('click', function(e) {
                                              if(this.checked) {
                                                  d3.selectAll('.' + this.id).each(function(d, i) {
                                                      if(i!==0) {
                                                          this.style.display = 'none'
                                                      }
                                                  })
                                              } else {
                                                  d3.selectAll('.' + this.id).each(function(d, i) {
                                                      if(i!==0) {
                                                          this.style.display = 'table-row'
                                                      }
                                                  })
                                              }

                                          })
                                      }
                                      tr.append('td').attr('class', 'rpd-value');
                                      if (config.showTypes) tr.append('td').attr('class', 'rpd-type').text(outlet.type);
                                      var name = tr.append('td').attr('class', 'rpd-name').text(outlet.label || outlet.def.label || outlet.alias);
                                      for(var i=0; i<outlet.space; i++) {
                                          name.append('span').attr('class', 'rpd-obj-space').text('');
                                      }
                                  } else {
                                      tr.append('td').attr('class', 'rpd-connector');
                                      tr.append('td').attr('class', 'rpd-value');
                                      if (config.showTypes) tr.append('td').attr('class', 'rpd-type').text(outlet.type);
                                      tr.append('td').attr('class', 'rpd-name').text(outlet.label || outlet.def.label || outlet.alias);
                                  }
                              }
                          });
        outletToConnector[outlet.id] = outletElm.select('.rpd-connector');
        return { element: outletElm.node() };
    },

    createLink: function(link) {
        var linkElm = d3.select(document.createElement('span'))
                        .attr('class', 'rpd-link')
                        .style('position', 'absolute')
                        .style('transform-origin', 'left top')
                        .style('-webkit-transform-origin', 'left top');
        return {
            element: linkElm.node(),
            rotate: function(x0, y0, x1, y1) {
                var distance = Math.sqrt(((x0 - x1) * (x0 - x1)) +
                                         ((y0 - y1) * (y0 - y1)));
                var angle = Math.atan2(y1 - y0, x1 - x0);
                linkElm.style('left', x0 + 'px').style('top', y0 + 'px')
                       .style('width', Math.floor(distance) + 'px')
                       .style('transform', 'rotateZ(' + angle + 'rad)')
                       .style('-webkit-transform', 'rotateZ(' + angle + 'rad)');
            }
        }
    },

    getInletPos: function(inlet) {
        var connectorPos = getPos(inletToConnector[inlet.id].node());
        return { x: connectorPos.x, y: connectorPos.y - 1 };;
    },

    getOutletPos: function(outlet) {
        var connectorPos = getPos(outletToConnector[outlet.id].node());
        return { x: connectorPos.x, y: connectorPos.y - 1 };
    },

    getLocalPos: function(pos) {
        if (!lastCanvas) return pos;
        // calculate once on patch switch?
        var canvasPos = getPos(lastCanvas.node());
        return { x: pos.x - canvasPos.x, y: pos.y - canvasPos.y - 1 };
    },

    onPatchSwitch: function(patch, canvas) {
        lastCanvas = d3.select(canvas);
    }

};

});

})(this);
