"use strict";

var sonos = require('sonos');
var portastic = require('portastic');
var ip = require('ip');
var NodeTunes = require('nodetunes');
var Nicercast = require('nicercast');
var flags = require('flags');

var APP_NAME='SonoAir';

flags.defineBoolean('diagnostics', false, 'run diagnostics utility');
flags.defineBoolean('version', false, 'return version number');
flags.defineInteger('timeout', 5, 'disconnect timeout (in seconds)');
flags.defineBoolean('verbose', false, 'show verbose output');
flags.defineString('radioname', APP_NAME, 'define service name');
flags.defineStringList('device-list', [], 'device ips separated by commas, e.g. --device-list 192.168.1.31, 192.168.1.41. ips can also contain port, e.g. 192.168.1.32:1400');
flags.parse();


// DUPLICATE FIX (BEGIN)

var devices = [];

var deviceExists = function(device){
  return (devices.indexOf(device.host+':'+device.port) >= 0);
};

var pushDevice = function(device){
  var deviceName =  device.host+':'+device.port;
  if (!deviceExists(deviceName)) {
    devices.push(deviceName);
  }
};

// DUPLICATE FIX (END)

var setupDevice = function(device) {
		device.getZoneAttrs(function(err, zoneAttrs) {
        if (err) throw err;

        var deviceName = zoneAttrs.CurrentZoneName;

        console.log('Setting up', APP_NAME, 'for', deviceName, '{' + device.host + ':' + device.port + '}');

        var airplayServer = new NodeTunes({
          serverName: deviceName + ' (' + flags.get('radioname') + ')',
          verbose: flags.get('verbose'),
          controlTimeout: flags.get('timeout')
        });

        var clientName = flags.get('radioname');
        airplayServer.on('clientNameChange', function(name) {
          clientName = flags.get('radioname') + ' @ ' + name;
        });

        airplayServer.on('error', function(err) {
          if (err.code === 415) {
            console.error('Warning!', err.message);
            console.error('AirSonos currently does not support codecs used by applications such as iTunes or AirFoil.');
            console.error('Progress on this issue: https://github.com/stephen/nodetunes/issues/1');
          } else {
            console.error('Unknown error:');
            console.error(err);
          }
        })

        airplayServer.on('clientConnected', function(audioStream) {

          portastic.find({
            min : 8000,
            max : 8050,
            retrieve: 1
          }, function(err, port) {
            if (err) throw err;

            var icecastServer = new Nicercast(audioStream, {
              name: flags.get('radioname') + ' @ ' + deviceName
            });

            airplayServer.on('metadataChange', function(metadata) {
              if (metadata.minm)
                icecastServer.setMetadata(metadata.minm + (metadata.asar ? ' - ' + metadata.asar : '') + (metadata.asal ? ' (' + metadata.asal +  ')' : ''));
            });

            airplayServer.on('clientDisconnected', function() {
              icecastServer.stop();
            });

            icecastServer.start(port);

            device.play({
              uri: 'x-rincon-mp3radio://' + ip.address() + ':' + port + '/listen.m3u',
              metadata: '<?xml version="1.0"?>' +
                '<DIDL-Lite xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:upnp="urn:schemas-upnp-org:metadata-1-0/upnp/" xmlns:r="urn:schemas-rinconnetworks-com:metadata-1-0/" xmlns="urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/">' +
                '<item id="R:0/0/49" parentID="R:0/0" restricted="true">' +
                '<dc:title>' + clientName + '</dc:title>' +
                '<upnp:class>object.item.audioItem.audioBroadcast</upnp:class>' +
                '<desc id="cdudn" nameSpace="urn:schemas-rinconnetworks-com:metadata-1-0/">SA_RINCON65031_</desc>' +
                '</item>' +
                '</DIDL-Lite>'
            });

          });
        });

        airplayServer.on('clientDisconnected', function() {
          device.stop(function() {});
        });

        airplayServer.on('volumeChange', function(vol) {
          vol = 100 - Math.floor(-1 * (Math.max(vol, -30) / 30) * 100);
          device.setVolume(vol, function() {
            // ?
          });
        });

        airplayServer.start();
      });
};



if (flags.get('version')) {

  var pjson = require('../package.json');
  console.log(pjson.version);

} else if (flags.get('diagnostics')) {

  var diag = require('./diagnostics');
  diag();

} else if (flags.get('device-list').length > 0) {

  var deviceList = flags.get('device-list');
  deviceList.forEach (function(device){

	var sonosDevice;

	var ipAddress = device.split(':');
    if (ipAddress.length  == 1) {
	  sonosDevice = new sonos.Sonos(ipAddress);
    } else if (ipAddress.length == 2) {
      sonosDevice = new sonos.Sonos(ipAddress[0], ipAddress[1]);
    } else {
	  console.error('Error: --device-list contains an incorrect entry: ' + ipAddress);
	}

	setupDevice(sonosDevice);
  }); // end for each device
} else {

  console.log('Searching for Sonos devices on network...');
  sonos.LogicalDevice.search(function(err, devices) {
    devices.forEach(function(device) {

// DUPLICATE FIX (BEGIN)
      if (deviceExists(device)) {
        return; // return early if device exists multiple times
      } else {
        pushDevice(device);
      }
// DUPLICATE FIX (END)

     setupDevice(device);

  });
  });
}
