/*  Copyright (C) 2016 Milan Pässler
    Copyright (C) 2016 HopGlass Server contributors

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published
    by the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>. */

'use strict'

var async = require('async')
var _ = require('lodash')

var config = {
  /* eslint-disable quotes */
  "origin": "nodes.community.freifunk.net.",
  "defaultTtl": 86400,
  "ns": "ns1.community.freifunk.net.",
  "postmaster": "admin+community.freifunk.net.",
  "refresh": 28800,
  "retry": 7200,
  "expire": 864000,
  "minTtl": 86400,
  "nameservers": [
    "ns1.community.freifunk.net.",
    "ns2.community.freifunk.net."
  ],
  "subdomainNet": "0:0:0:0::/64",
  "namePadding" : 40
}

module.exports = function(receiver, sharedConfig) {
  _.merge(config, sharedConfig.named)
  
  //Named nodes.zone
  function getZone(stream, query) {
    stream.writeHead(200, { 'Content-Type': 'text/plain' })
    var data = receiver.getData(query)

    String.prototype.padRight = function(l,c) {
      if (this.length > l) {
        return this
      } else {
        return this+Array(l-this.length+1).join(c||" ")
      }
    }

    stream.write('$ORIGIN' + " " + config.origin + '\n')
    stream.write('$TTL ' + config.minTtl + '\n\n')
    stream.write('@ IN SOA ' + config.ns + ' ' + config.postmaster.replace("@", "+") + ' (\n')
    stream.write(' ' + Date.now() + '       ; serial number\n')
    stream.write(' ' + config.refresh + ' ; Refresh\n')
    stream.write(' ' + config.retry + '   ; Retry\n')
    stream.write(' ' + config.expire + '  ; Expire\n')
    stream.write(' ' + config.minTtl + ' ; Min TTL\n')
    stream.write(')\n')
    for (var ns in config.nameservers) { 
      stream.write('@ IN NS ' + config.nameservers[ns] + '\n')
    }
    stream.write('\n')

    var subdomain = config.subdomainNet.split(":").slice(0,2).join(":")
    
    async.forEachOf(data, function(n, k, finished) {
      if (_.has(n, 'nodeinfo.network.addresses')) {
        var addrobj = _.get(n, 'nodeinfo.network.addresses')
        var address = undefined
        for (var a in addrobj) {
          if (addrobj[a].indexOf(subdomain) === 0) {
            address = addrobj[a]
          }
        }
        if (address) {
          var padding = config.namePadding
          var nodeid  = _.get(n, 'nodeinfo.node_id')
          stream.write(nodeid.padRight(padding," ") + ' IN AAAA ' + address + '\n')
          if (config.mapTemplate) {
            var mapurl = config.mapTemplate.replace("{node_id}",nodeid)
            stream.write(nodeid.padRight(padding," ") + ' IN TXT  "' + mapurl + '"\n')
          }
          if (_.has(n, 'nodeinfo.hostname')) {
            var hostname = _.get(n, 'nodeinfo.hostname')
            stream.write(hostname.padRight(padding," ") + ' IN AAAA ' + address + '\n') 
            if (config.mapTemplate) {
              stream.write(hostname.padRight(padding," ") + ' IN TXT  "' + mapurl + '"\n')
            }
          }
          stream.write('\n')
        }
      }
      finished()
    }, function() {
      stream.end()
    })
    stream.end()
  }

  return {
    /* eslint-disable quotes */
    "nodes.zone": getZone
  }
}

@@ -1516,51 +1516,464 @@
     
-String.prototype.padRight = function(l,c) %7B
+function namedString(s) %7B%0A      //limit length%0A      var r = s.substring(0,50)%0A      //remove leading and trailing minus%0A      r = r.replace(/%5E-+/,'').replace(/-+$/,'')%0A      //remove non alphanumerics and make lc%0A      r = r.replace(/-+/g,'_').replace(/_+/g,'_')%0A      r = r.replace(/%5CW/g, '').toLowerCase()%0A      //no underscores and no repeating minuses%0A      r = r.replace(/_+/g,'-').replace(/-+/g,'-')%0A      // padding%0A      var l = config.namePadding
 %0A   
@@ -1979,20 +1979,17 @@
     if (
-this
+r
 .length 
@@ -2010,20 +2010,17 @@
  return 
-this
+r
 %0A      %7D
@@ -2042,20 +2042,17 @@
  return 
-this
+r
 +Array(l
@@ -2052,20 +2052,17 @@
 Array(l-
-this
+r
 .length+
@@ -2069,17 +2069,19 @@
 1).join(
-c
+%22 %22
 %7C%7C%22 %22)%0A 
@@ -3183,51 +3183,8 @@
 ) %7B%0A
-          var padding = config.namePadding%0A
     
@@ -3260,34 +3260,25 @@
 te(n
-odeid.padRight(padding,%22 %22
+amedString(nodeid
 ) + 
@@ -3445,34 +3445,25 @@
 te(n
-odeid.padRight(padding,%22 %22
+amedString(nodeid
 ) + 
@@ -3625,50 +3625,82 @@
     
-stream.write(hostname.padRight(padding,%22 %22
+if (hostname !== nodeid) %7B%0A              stream.write(namedString(hostname
 ) + 
@@ -3730,16 +3730,18 @@
  '%5Cn') %0A
+  
         
@@ -3776,32 +3776,34 @@
 %7B%0A              
+  
 stream.write(hos
@@ -3803,37 +3803,28 @@
 ite(
-hostname.padRight(padding,%22 %22
+namedString(hostname
 ) + 
@@ -3846,32 +3846,48 @@
 mapurl + '%22%5Cn')%0A
+              %7D%0A
             %7D%0A  

remove non alphanum chars from routername