/**
 * Local settings page
 * DDVTECH
 * for more information, see http://mistserver.org/index.php?title=Stand-alone_Configuration_Page
 */
 
 
/**
 * Store a local copy of the data send by the server.
 * server is the URL, credentials hold the username, password and authstring and settings is the local copy.
 */
  var settings =
  {
    server: '',
    credentials:
    {
      username: "",
      password: "",
      authstring: ""
    },
    settings: {}
  };
  
  
/**
 *  Table for long/short limit names
 */
  var ltypes =
  [
    ['kbps_max', 'Current bandwidth'],
    ['users', 'Concurrent users'],
    ['geo', 'Geolimited'],
    ['host', 'Hostlimited']
  ];
  
  /* Not currently supported but may return at a later time:
    ['kb_total', 'Total bandwidth'],
    ['duration', 'Duration'],
    ['str_kbps_min', 'Minimum bitrate'],
    ['str_kbps_max', 'Maximum bitrate']
  /*
  
  
/**
 *  When the page loads, fix the menu and show the correct tab
 */
  $(document).ready(function()
  {
    $('#nav').children().each(function()
    {
      $(this).click(function()
      {
        // remove currently selected' class
        $('#nav').children().each(function()
        {
          $(this).attr('class', '');
        });
        
        // select this one
        $(this).attr('class', 'selected');
        
        // show correct tab
        showTab($(this).text());
      });
      
    });
    
    // show login 'tab' and hide menu
    showTab('login');
    $('#nav').css('visibility', 'hidden');
  });
  
  
  // used on the overview and streams page. cleared when switching to another 'tab'.
  var sinterval = null;
  
  // and this one is used on the protocols page.
  var pinterval = null;
  
  // ..and the logs page.
  var logsinterval = null;
  
  // what kind of streams should be displayed? Format is [recorded, live];
  var streamsdisplay = [true, true];
  
  // used on the overview page to decide then to ask the controller for an update check
  var updatelastchecked;
  
/**
 * Display a certain page. It contains a (giant) switch-statement, that builds a page depending on the tab requested
 * @param name the name of the tab
 * @param streamname only used when editing streams or protocols, the name of the edited (or new) stream/protocol. Also used with the 'embed' tab
 */
  function showTab(name, streamname)
  {
    // clear page and refresh interval
    $('#page').html('');
    clearInterval(sinterval);
    clearInterval(pinterval);
    clearInterval(logsinterval);
    
    $('#page').removeClass('LTS-only');
    $('#page').off('mouseenter mouseleave');
    removeTooltip();
    
    switch(name)
    {
      case 'login':
      
        var host = $('<input>').attr('type', 'text').attr('placeholder', 'HTTP://' + (location.host == '' ? 'localhost:4242' : location.host) + '/api');
        var user = $('<input>').attr('type', 'text').attr('placeholder', 'USERNAME');
        var pass = $('<input>').attr('type', 'password').attr('placeholder', 'PASSWORD');
        var conn = $('<button>').click(function()	
        {
          // get login info
          settings.credentials.username = user.val();
          settings.credentials.password = pass.val();
          settings.server = host.val() == '' ? host.attr('placeholder') : host.val().toLowerCase();
          
          // save username, URL in address
          location.hash = user.val() + '@' + settings.server;
          
          // try to login
          setHeaderState('logingin');
          
          loadSettings(function(errorstr)
          {
            if(errorstr == '')
            {
              setHeaderState('connected');
              
              $('#nav').css('visibility', 'visible');
              
              showTab('overview');
              
              // show overview as current tab - this only happens when logging out and then in
              $('#nav').children().each(function()
              {
                if($(this).text() != 'overview')
                {
                  $(this).attr('class', '');
                }else{
                  $(this).attr('class', 'selected');
                }
              });
              
            }else{
              setHeaderState('disconnected');
              $('#header-host').text('');
              $('#page').append($('<p>').text(errorstr));
            }
          });
        }).text('login');
        
        $('#page').append(
          $('<div>').attr('id', 'login').append(host).append(user).append(pass).append(conn)
        );
        
        // if we 'enter' in host, user or pass we should try to login.
        function hand(e)
        {
          if(e.keyCode == 13)
          {
            conn.trigger('click');  // conn = login button
          }
        }
        
        host.keypress(hand);
        user.keypress(hand);
        pass.keypress(hand);
        
        // retrieve address hash from URL
        var adr = location.hash.replace('#', '').split('@');
        
        if(adr.length == 2)
        {
          // put it in the page
          host.val(adr[1]);
          user.val(adr[0]);
        }
        
        break;
        
      case 'overview':
        
        
        loadSettings(function(){
        
          $uptodate = null;
          if (settings.settings.LTS == 1)
          {
            if ((settings.settings.update == undefined) || (updatelastchecked == undefined) || ((new Date()).getTime() - updatelastchecked > 3600000))
            {
              settings.settings.checkupdate = true;
              settings.settings.update = {};
              updatelastchecked = (new Date()).getTime();
              loadSettings(function()
              { 
                showTab('overview'); 
              });
            }
            else
            {
              if (settings.settings.update.uptodate == 0)
              {
                $uptodate = $('<label>').text('version check').css('line-height','30px');
                $uptodate.append(
                  $('<span>').attr('class','red').text('Outdated version!').append(
                    $('<button>').text('update').click(function(){
                      settings.settings.autoupdate = true;
                      loadSettings();
                    })
                  )
                );
              }
            }
          }
          if (settings.settings.config.basepath == undefined) 
          {
            settings.settings.config.basepath = "";
          }
          
          $('#page').append(
            $('<div>').attr('id', 'editserver').append(
              $('<label>').attr('for', 'config-host').text('host').append(
                $('<input>').attr('type', 'text').attr('placeholder', 'HOST').attr('id', 'config-host').attr('value', settings.settings.config.host)
              )
            ).append(
              $('<label>').attr('for', 'config-name').text('name').append(
                $('<input>').attr('type', 'text').attr('placeholder', 'NAME').attr('id', 'config-name').attr('value', settings.settings.config.name)
              )
            ).append(
              $('<label>').text('Version').append(
                $('<span>').text(settings.settings.config.version)
              ).append($uptodate)
            ).append(
              $('<label>').text('Base path').append(
                $('<input>').attr('type','text').attr('placeholder','BASE PATH').attr('id','config-basepath').val(settings.settings.config.basepath)
              )
            ).append(
              $('<label>').text('time').append(
                $('<span>').text( formatDate(settings.settings.config.time) )
              )
            ).append(
              $('<label>').text('Streams').append(
                $('<span>').attr('id', 'cur_streams_online').text('retrieving data...')
              )
            ).append(
              $('<label>').text('Viewers').append(
                $('<span>').attr('id', 'cur_num_viewers').text('retrieving data...')
              )
            )
          );
          
          function showStats()
          {
            getStatData(function(data)
            {
              $('#cur_streams_online').html('').text(data.streams[0] + ' of ' + data.streams[1] + ' online');
              $('#cur_num_viewers').html('').text(data.viewers);
            });
          }
          
          // refresh the stream status + viewers
          sinterval = setInterval(function()
          {
            showStats();
          }, 10000);
          
          showStats();
          
          $('#editserver').append(
            $('<button>').attr('class', 'floatright').click(function()
            {
              var host = $('#config-host').val();
              var name = $('#config-name').val();
              var path = $('#config-basepath').val();
              
              settings.settings.config.host = host;
              settings.settings.config.name = name;
              settings.settings.config.basepath = path;
              
              loadSettings(function()
              {
                showTab('overview');
              });
            }).text( 'save' )
          );
          
          var forcesave = $('<div>').attr('id', 'forcesave');
          
          forcesave.append(
            $('<p>').text('Click the button below to force an immediate settings save. This differs from a regular save to memory and file save on exit by saving directly to file while operating. This may slow server processes for a short period of time.')
          ).append(
            $('<button>').click(function()
            {
              if(confirmDelete('Are you sure you want to force a JSON save?') == true)
              {
                var host = $('#config-host').val();
                var name = $('#config-name').val();
                var path = $('#config-basepath').val();
                
                settings.settings.config.host = host;
                settings.settings.config.name = name;
                settings.settings.config.basepath = path;
                
                loadSettings(function()
                {
                  forceJSONSave();
                  showTab('overview');
                });
              }
            }).text( 'force save to JSON file' )
          );
          
          $('#page').append(forcesave);
        });
        
        break;
        
        
      case 'protocols':
        
        $table = $('<table>');
        $table.html("<thead><th>Protocol</th><th>Status</th><th>Settings</th><th></th></thead>");
        $tbody = $('<tbody>');
        
        var tr, i, protocol,
          len = (settings.settings.config.protocols ? settings.settings.config.protocols.length : 0);
        
        $tbody.html('');
        pids = [];
        
        for(i = 0; i < len; i++)
        {
          protocol = settings.settings.config.protocols[i];  // local copy
          pids.push(i);
          
          tr = $('<tr>').attr('id', 'protocol-' + i);
          
          tr.append( $('<td>').text( protocol.connector ) );
          
          //tr.append( $('<td>').html( formatStatus( protocol.online ) ) );
          tr.append( $('<td>').html(formatStatus()));
          
          s = "";
          for (option in protocol) 
          {
            if ((option != 'connector') && (option != 'online')) 
            {
              s += option+': '+((protocol[option] == '') ||  (protocol[option] == 0) ? 'default' : protocol[option] )+', ';
            }
          }
          s = s.slice(0,-2);
            
          tr.append( $('<td>').text( s ) ); 
          
          tr.append( $('<td>').attr('class', 'center').append( $('<button>').text('edit').click(function()
          {
            id = $(this).parent().parent().attr('id').replace('protocol-', '');
            showTab('editprotocol', id);
          }) ).append( $('<button>').click(function()
          {
            if(confirmDelete('Are you sure you want to delete this protocol?') == true)
            {
              var id = Number($(this).parent().parent().attr('id').replace('protocol-', ''));
              var pid = pids.indexOf(id);
              settings.settings.config.protocols.splice(pid, 1);
              loadSettings(function()
              {
                showTab('protocols');
              });
            }
          }).text('delete') ) );
          
          $tbody.append(tr);
        }
          
        $table.append($tbody);
        $('#page').append($table);
           
        $('#page').append(
          $('<button>').attr('class', 'floatright').click(function()
          {
            showTab('editprotocol', 'new');
          }).text('add new')
        );
        
        function refreshProtocolStatus() 
        {
          getData(function(data)
          {
            $('tbody tr').each(function()
            {
              protocolstatus = null;
              pid = $(this).attr('id').split('-')[1];
              if (data.config.protocols[pid] == undefined) 
              { 
                protocolstatus = 'Protocol config missing.. reloading tab'; 
                showTab('protocol');
              }
              else {
                if (data.config.protocols[pid].online == undefined) 
                {
                  setTimeout(function()
                  {
                    refreshProtocolStatus();
                  },1000);
                }
                protocolstatus = data.config.protocols[pid].online;
              }
              $(this).children(':nth-child(2)').html( formatStatus( protocolstatus ) );
            });
          });
        }
        
        pinterval = setInterval(function()
        {
          refreshProtocolStatus();
        },10000);
        refreshProtocolStatus();
        
        break;
        
      case 'editprotocol':
        if (streamname != 'new') 
        { 
          currentdata = settings.settings.config.protocols[streamname]; 
        }
        
        currentconnectors = [];
        // build a list of the current connectors to see if the dependencies are already configured
        for (var index in settings.settings.config.protocols) 
        { 
          currentconnectors.push(settings.settings.config.protocols[index].connector);
        }
        
        function buildProtocolParameterFields(data,required)
        {
          for (fieldname in data)
          {
            switch(data[fieldname].type)
            {
              case 'str':
                var inputType = 'text'
                break;
              case 'uint':
                var inputType = 'number'
                var func = 'uint'
                break;
              case 'int':
                var inputType = 'number'
                break;
            }
            $i = $('<input>').attr('type',inputType).attr('id','protocol-parameter-'+fieldname);
            if (func == 'uint') 
            {
              $i.addClass('uint');
            }
            if (required) 
            {
              $i.addClass('required');
            }
            $protocolfields.append(
              $('<label>').text(data[fieldname].name).attr('title',data[fieldname].help).append($i)
            );
          }
        }
        
        function buildProtocolFields(selectedProtocol) 
        {
          data = settings.settings.capabilities.connectors[selectedProtocol];
          
          $t = $('<p>').text(data.desc);
          if ((typeof data.deps != 'undefined') && (data.deps))
          {
            $t.append($('<p>').text('Dependencies:'));
            $s = $('<ul>');
            deps = data.deps.split(',');
            for (var index in deps) 
            {
              t = deps[index];
              if ($.inArray(deps[index],currentconnectors) < 0) 
              {
                $u = $('<span>').text(' (Not yet configured!)').addClass('red');
              }else{
                $u = $('<span>').text(' (Configured)').addClass('green');
              }
              $s.append($('<li>').text(t).append($u));
            }
            $t.append($s);
          }						 
          $('#protocoldesc').html( $t );
          
          $protocolfields = $('<div>');
          if (typeof data.required != 'undefined') 
          {
            $protocolfields.append( $('<p>').text('Required parameters') );
            buildProtocolParameterFields(data.required,true);
          }
          if (typeof data.optional != 'undefined') 
          {
            $protocolfields.append( $('<p>').text('Optional parameters') );
            buildProtocolParameterFields(data.optional,false);
          }
          $('#protocolfields').html($protocolfields);
          if (streamname != 'new') 
          {
            for (fieldname in currentdata) 
            {
              if ((fieldname != 'connector') && (fieldname != 'online')) 
              { 
                $('#protocol-parameter-'+fieldname).val(currentdata[fieldname]);
              }
            }
          }
        }
          
        loadSettings(function()
        {
          if (streamname == 'new') { t = 'add new protocol'; }
          else { t = 'edit protocol'; }
          
          $('#page').append( $('<p>').text(t) );
          
          $selectprotocol = $('<select>').attr('id', 'edit-protocol').change(function()
          {
            buildProtocolFields($(this).children(':selected').val());
          });
          for(protocol in settings.settings.capabilities.connectors)
          {
            if ((streamname != 'new') && (currentdata.connector == protocol)) {
              $selectprotocol.append(
                $('<option>').attr('value', protocol).attr('selected','selected').text(protocol)
              );
            }else{
              $selectprotocol.append(
                $('<option>').attr('value', protocol).text(protocol)
             );
            }
          }
          
          $div = $('<div>').attr('id', 'editprotocol');
          $div.append( 
            $('<label>').attr('for', 'protocol-edit-protocol').text('protocol').append(
              $selectprotocol
            )
          );
          
          $('#page').append( $div );
          $('#editprotocol').append( $('<div>').attr('id','protocoldesc') );
          $('#editprotocol').append( $('<div>').attr('id','protocolfields') );
          $('#editprotocol').append(
            $('<button>').text('cancel').addClass('floatright').click(function()
            {
              showTab('protocols');
            })
          );
          $('#editprotocol').append(
            $('<button>').text('save').addClass('floatright').click(function()
            {
              error = false;
              //check if all required fields have contents
              $('input.required').each(function()
              { 
                if ($(this).val() == '') 
                {
                  $(this).focus();
                  $(this).parent().addClass('red');
                  error = true;
                }
              });
              
              $('input[type="number"]').each(function()
              { 
                if ($(this).val() != '') {
                  //make sure this is a number
                  if (isNaN($(this).val())) 
                  {
                    $(this).focus();
                    $(this).parent().addClass('red');
                    error = true;
                  }
                  else
                  {
                    //turn all numbers into integers
                    $(this).val(Math.floor($(this).val()));
                  }
                }
              });
              //check if all uints are actually uints
              $('input.uint').each(function()
              { 
                if ($(this).val() < 0) 
                {
                  $(this).focus();
                  $(this).parent().addClass('red');
                  error = true;
                }
              });
              if (error) { return; }
              if(!settings.settings.config.protocols)
              {
                settings.settings.config.protocols = [];
              }
              
              connectorval = $('#edit-protocol').val()
              var newprotocol =
              {
                connector: connectorval
              };
              
              $('input').each(function(){
                newprotocol[$(this).attr('id').split('-')[2]] = $(this).val();;
              });
              newprotocol.online = -1;
              if (streamname == 'new') {
                settings.settings.config.protocols.push(newprotocol);
              }else{
                settings.settings.config.protocols[streamname] = newprotocol;
              }
              
              loadSettings(function()
              {
                showTab('protocols');
              });
            })
          );
          
          buildProtocolFields($('select#edit-protocol :selected').val());
          
        });
        
        break;
        
      case 'streams':
        
        // the filter element containr
        $div = $('<div>').attr('id', 'streams-filter');
        
        // filters the table. uses the streamsdisplay
        function filterTable()
        {
          $('#streams-list-tbody').children().each(function(k, v)
          {
            var type = $($(v).children()[1]).text().toLowerCase();
            
            $(v).show();
            
            if(type == 'recorded' && streamsdisplay[0] == false)
            {
              $(v).hide();
            }
            
            if(type == 'live' && streamsdisplay[1] == false)
            {
              $(v).hide();
            }
          });
        }
        
        function filterOn(event, elem)
        {
          if(event.target.id == '')
          {
            return;  // label click goes bubbles on checkbox, so ignore it
          }
          
          var what = $(elem).text();
          
          if(what == 'recorded')
          {
            streamsdisplay[0] = !streamsdisplay[0];
            $('#stream-filter-recorded').attr('checked', streamsdisplay[0]);
          }else{
            streamsdisplay[1] = !streamsdisplay[1];
            $('#stream-filter-live').attr('checked', streamsdisplay[1]);
          }
          
          filterTable();
        }
        $div.append(
          $('<label>').attr('for', 'stream-filter-recorded').text('recorded').append(
            $('<input>').attr('type', 'checkbox').attr('id', 'stream-filter-recorded').attr('checked', streamsdisplay[0])
              ).click(function(event)
              {
                filterOn(event, this);
              })
        );
        $div.append(
          $('<label>').attr('for', 'stream-filter-live').text('live').append(
            $('<input>').attr('type', 'checkbox').attr('id', 'stream-filter-live').attr('checked', streamsdisplay[1])
              ).click(function(event)
              {
                filterOn(event, this);
              })
        );
        $('#page').append($div);
        
        // refresh every streams' data (status and viewer count)
        function refreshStreams()
        {
          getStreamsData(function(streams)
          {
            $('tbody#streams-list-tbody tr').each(function()
            {
              streamstatus = null;
              stream = $(this).attr('id').split('-')[1];
              if (streams[stream] == undefined) 
              { 
                streamstatus = 'Stream config missing - reloading tab'; 
                showTab('streams');
              }
              else
              {
                if (streams[stream][2])
                {
                  //there is an error
                  streamstatus = formatStatus(streams[stream][0],streams[stream][2]);
                }
                else
                {
                  streamstatus = formatStatus(streams[stream][0]);
                }
                $(this).children(':nth-child(5)').html(formatStatus(streamstatus));
                $(this).children(':nth-child(6)').html(streams[stream][1]);
              }
            });
          });
        };
        
        sinterval = setInterval(function()
        {
          refreshStreams();
        }, 10000);
        
        refreshStreams();
        
        $table = $('<table>');
        $table.html("<thead><th class=sort-type-int>Id</th><th class=sort-type-string>Type</th><th class=dontsort>Embed</th><th class='sort-type-string sortdesc'>Name</th><th class=sort-type-string>Status</th><th class=sort-type-int>Viewers</th><th class=dontsort>Edit</th></thead>");
        $tbody = $('<tbody>');
            
        var stream, cstr, $tr;
        
        $tbody.html('').attr('id', 'streams-list-tbody');
        
        for(stream in settings.settings.streams)
        {
          
          //backwards compatibility
          //if sid does not yet exist, create it
          if (settings.settings.streams[stream].sid == undefined) 
          {
            sid = 0;
            for (strm in settings.settings.streams)
            {
              if (settings.settings.streams[strm].sid != undefined) 
              { 
                sid = Math.max(sid,settings.settings.streams[strm].sid); 
              }
            }
            sid += 1;
            settings.settings.streams[stream].sid = sid;
          }
          //if .source does not exist, create it
          if ((settings.settings.streams[stream].source == undefined) && (settings.settings.streams[stream].channel != undefined))
          {
            settings.settings.streams[stream].source = settings.settings.streams[stream].channel.URL;
          }
          
          var cstr = settings.settings.streams[stream];
          
          $tr = $('<tr>').attr('id', 'stream-' + stream);
          
          $tr.append( $('<td>').text( cstr.sid ) );
          
          $tr.append( $('<td>').text( TypeofResource( cstr.source ) ) );
          
          $tr.append( $('<td>').append( $('<button>').text('embed').click(function()
          {
            var sname = $(this).parent().parent().attr('id').replace('stream-', '');
            showTab('embed', sname);
          }) ) );  // end function, end click(), end append(), end append(). Huzzah jQuery.
          
          if ( cstr.name == undefined ) { cstr.name = ''; }
          
          $tr.append( $('<td>').text( cstr.name ) );
          
          /*
          if (cstr.error) 
          {
            $tr.append( $('<td>').html( formatStatus( cstr.online, cstr.error ) ) );
          }
          else
          {
            $tr.append( $('<td>').html( formatStatus( cstr.online ) ) );
          }*/
          $tr.append( $('<td>').html( formatStatus() ) );
          
          var cviewers = 0;
          
          if(settings.settings.statistics && settings.settings.statistics[stream])
          {
            if(settings.settings.statistics[stream] && settings.settings.statistics[stream].curr)
            {
              for(viewer in settings.settings.statistics[stream].curr)
              {
                cviewers++;
              }
            }
          }else{
            cviewers = 0;
          }
          
          $tr.append( $('<td>').text( cviewers ) );
          
          $tr.append( $('<td>').append( $('<button>').text('edit').click(function()
          {
            var sname = $(this).parent().parent().attr('id').replace('stream-', '');
            
            showTab('editstream', sname);
          }) ) );  // end function, end click, end append, end append.
          
          $tbody.append($tr);
          
          //quickly re-check if the streams are online now
          if (cstr.online == undefined) 
          {
            setTimeout(function()
            {
              refreshStreams();
            }, 1000);
          }
        }
        
        $table.append($tbody).addClass('sortable');
        $table.stupidtable();
        $('#page').append($table);
        
        // on page load, also filter with the (users' defined) stream filter
        filterTable();
        
        $('#page').append(
          $('<button>').attr('class', 'floatright').click(function()
          {
            showTab('editstream', 'new');
          }).text('add new')
        );
        
        break;
        
      case 'editstream':
        
        var sdata, title;
        
        if(streamname == 'new')
        {
          sdata =
          {
            'name': '',
            'source': '',
            'limits': [],
            'preset':
            {
              'cmd': ''
            }
          };
          title = 'add new stream';
        }else{
          sdata = settings.settings.streams[streamname];
          title = 'edit stream "' + sdata.name + '"';
        }
        sdata = $.extend({
          'name': '',
          'source': '',
          'limits': [],
          'preset':
          {
            'cmd': ''
          }
        },sdata);
          
        $('#page').append( $('<p>').text(title) );
          
        $('#page').append(
          $('<div>').attr('id', 'editserver').append(
            $('<label>').attr('for', 'stream-edit-name').text('name [case insensitive, no special chars]').append(
              $('<input>').attr('type', 'text').attr('placeholder', 'NAME').attr('id', 'stream-edit-name').attr('value', sdata.name)
            )
          ).append(
            $('<label>').attr('for', 'stream-edit-source').text('source').append(
              $('<input>').attr('type', 'text').attr('placeholder', '/path/name.dtsc or push://host/name').attr('id', 'stream-edit-source').attr('value', sdata.source).keyup(function(){
                var text = $(this).val();
                if(text.charAt(0) == '/'){
                  $('.live-only').hide();
                  $('.live-only').children('label').children('input').val('');
                }
                else{
                  $('.live-only').show();
                }
              })
            )
          )
        );
        
        // BUFFER
        if (sdata.DVR == undefined) { var DVR = ''; } else { var DVR = sdata.DVR; }
        $('#editserver').append(
          $('<span>').addClass('live-only').append(
            $('<label>').attr('id','stream-edit-buffer-label').attr('for','stream-edit-buffer').attr('title','Only applies to live streams').text('Buffer time [ms]').append(
             $('<input>').attr('type','text').attr('placeholder','2 keyframes').attr('id','stream-edit-buffer').attr('value', DVR)
            )
          )
        );
        
        // RECORD
        if (sdata.record == undefined) { var record = ''; } else { var record = sdata.record; }
        $('#editserver').append(
          $('<span>').addClass('live-only').addClass('LTS-only').append(
            $('<label>').attr('id','stream-edit-record-label').attr('for','stream-edit-record').attr('title','Only applies to live streams').text('Record to:').append(
             $('<input>').attr('type','text').attr('placeholder','2 keyframes').attr('id','stream-edit-record').attr('value', record).attr('placeholder','/path/to/filename.dtsc')
            )
          )
        );
        
        var text = $('#stream-edit-source').val();
        //if the source is not live, show any stuff marked as live-only
        if(text.charAt(0) == '/')
        {
          $('.live-only').hide();
          $('.live-only').children('label').children('input').val('');
        }else{
          $('.live-only').show();
        }
        
        $('#editserver').append(
          $('<button>').attr('class', 'floatright').click(function()
          {
            if(streamname == 'new')
            {
              showTab('streams');
            }else{
              if(confirmDelete('Are you sure you want to delete the stream "' + settings.settings.streams[streamname].name + '"?') == true)
              {
                delete settings.settings.streams[streamname];
                loadSettings(function()
                {
                  showTab('streams');
                });
              }
            }
          }).text( streamname == 'new' ? 'cancel' : 'delete' )
        );
        
        $('#editserver').append(
          $('<button>').attr('class', 'floatright').click(function()
          {
            var n = $('#stream-edit-name');
            var s = $('#stream-edit-source');
            var p = $('#stream-edit-preset');
            var b = $('#stream-edit-buffer');
            var r = $('#stream-edit-record');
            
            if(n.val() == ''){ n.focus(); return; }
            if(s.val() == ''){ s.focus(); return; }
            if((b.val() != '') && ((b.val() < 0) || (isNaN(b.val())))){ b.focus(); return; }
            
            var newname = n.val().replace(/([^a-zA-Z0-9_])/g, '').toLowerCase();
            
            sdata.name = newname;
            sdata.source = s.val();
            sdata.preset.cmd = p.val();
            sdata.online = -1;
            sdata.error = null;
            sdata.record = r.val();
            if (b.val() != '') { sdata.DVR = b.val(); }
            
            if(streamname == 'new')
            {
              streamname = newname;
              sdata.sid = 0;
              for (strm in settings.settings.streams)
              {
                sdata.sid = Math.max(sdata.sid,settings.settings.streams[strm].sid); 
              }
              sdata.sid += 1;
            }
            else 
            {
              sdata.sid = settings.settings.streams[streamname].sid;
            }
            
            if(!settings.settings.streams)
            {
              settings.settings.streams = {};
            }
            
            delete settings.settings.streams[streamname];
            
            settings.settings.streams[newname] = sdata;
            
            loadSettings(function()
            {
              showTab('streams');
            });
              
          }).text('save')
        );
        
        break;
        
      case 'embed':
        
        if(isThereAHTTPConnector())
        {
          var embedbase = 'http://' + parseURL(settings.server).host + ':' + getHTTPControllerPort() + '/';
          
          // TODO   .attr().html()   doesn't work... make this work in 2 lines again
          var iem = $('<p>').attr('class', 'nocapitals');
              iem.html('The info embed URL is <code>' + embedbase + 'info_' + streamname + '.js</code>');

          var eem = $('<p>').attr('class', 'nocapitals');
              eem.html('The embed embed URL is <code>' + embedbase + 'embed_' + streamname + '.js</code>');

          $('#page').append( iem );
          $('#page').append( eem );
          
          $('#page').append( $('<button>').text('preview').click(function()
          {
            showTab('preview', streamname);
          } ) );
          
        }else{
          $('#page').append( $('<p>').attr('class', 'nocapitals').text('Could\'t find a HTTP connector. Please add a HTTP connector on the "protocol" page.') );
        }
        
        break;
        
      case 'preview':
        
        var embed = 'http://' + parseURL(settings.server).host + ':' + getHTTPControllerPort() + '/embed_' + streamname + '.js';
        
        $('#page').append( $('<div>').attr('id', 'previewcontainer') );
        
        // jQuery doesn't work -> use DOM magic
        var script = document.createElement('script');
        script.src = embed;
        document.getElementById('previewcontainer').appendChild( script );
        
        break;
        
      case 'limits':
        /*if (settings.settings.LTS != 1) {
          $('#page').html('Limits are not supported in your version. Buy the LTS! :)');
          return;
        } */
        $cont = $('<span>').addClass('LTS-only');
        $('#page').append($cont);
      
        $table = $('<table>');
        $table.html("<thead><th>Hard/soft</th><th>Type</th><th>Value</th><th>Applies to</th><th>Action</th></thead>");
        $tbody = $('<tbody>');
        
        var i, tr, limit, stream, currentlims,
           alllimits = settings.settings.config.limits;
           
        for(stream in settings.settings.streams)
        {
          currentlims = settings.settings.streams[stream].limits;
          
          for (index in currentlims) {
            currentlims[index].appliesto = stream;
            currentlims[index].appliesi = index;
          }
          
          alllimits = alllimits.concat(currentlims);
        }
        
        len = alllimits.length;
        
        // remove old items
        $tbody.html('');
        
        //build current limits
        for(i = 0; i < len; i++)
        {
          limit = alllimits[i];
          $tbody.append(BuildLimitRow(limit));
        }
        for (stream in settings.settings.streams) {
          for (limit in settings.settings.streams[stream].limits) {
            delete settings.settings.streams[stream].limits[limit].appliesto;
            delete settings.settings.streams[stream].limits[limit].appliesi
          }
        }
         
        $table.append($tbody);
        $cont.append($table); 
        
        //tooltip
        $('.limits_type').live({
          "mouseover": function(e){
            removeTooltip();
            showTooltip(e,undefined,$(this).children(':selected').data('desc'));
          },
          "mouseout": function(){
            removeTooltip();
          }
        });
        $('.limits_name').live({
          "mouseover": function(e){
            removeTooltip();
            showTooltip(e,undefined,$(this).children(':selected').data('desc'));
          },
          "mouseout": function(){
            removeTooltip();
          }
        });
        
        //change limit value box on type change
        $('.limits_name').live("change", function(){
          var value = $(this).parents('.limits_row').find(".limits_val").val();
          $(this).parents('.limits_row').children('.limit_input_container').html('');
          BuildLimitRowInput(
           $(this).parents('.limits_row').children('.limit_input_container'),
           {
            'name': $(this).parents('.limits_row').find(".limits_name").val(),
            'type': $(this).parents('.limits_row').find(".limits_type").val(),
            'val': value
           }
          );
        });
        
        //build buttons
        $cont.append(
          $('<button>').text('Add limit').click(function(){
           $tbody.append(BuildLimitRow({"name":"kbps_max", "val":0, "type":"soft"}));
          })
        ).append($('<br>')).append(
          $('<button>').text('Save all').click(function(){
           //clear current limits
           settings.settings.config.limits = Array();
           for (str in settings.settings.streams) {
            settings.settings.streams[str].limits = Array();
           }
           
           //add new limits
           $tbody.children('tr').each(function(){
            var newval = null;
            switch ($(this).find(".limits_name").val()) {
              case 'geo':
                var entries = Array();
                $(this).find('.limit_listentry').each(function(){
                  var t = $(this).children(':selected').val();
                  if (t != ''){
                    entries.push(t);
                  }
                });
                newval = $(this).find('.limit_listtype').children(':selected').val() + entries.join(' ');
                break;
              case 'host':
              case 'time':
                var t = $(this).find('.limit_listentry').val();
                if ((t != undefined) && (t.toString().split(' ').length > 0)) {
                  newval = $(this).find('.limit_listtype').children(':selected').val() + t;
                }
                break;
              default:
                newval = $(this).find(".limits_val").val();
                break;
            }
            if (newval){
              obj = {"type": $(this).find(".limits_type").val(), "name":$(this).find(".limits_name").val(), "val":newval};
              if($(this).find('.new-limit-appliesto').val() == 'server') {
                settings.settings.config.limits.push(obj);
                //console.log('new server limit',obj);
              }else{
                settings.settings.streams[$(this).find('.new-limit-appliesto').val()].limits.push(obj);
                //console.log('new stream limit',$(this).find('.new-limit-appliesto').val(),obj);
              }
            }
           });
           loadSettings(function(){
            showTab('limits');
           });
          })
        );
        
        break;
        
      case 'conversion':
        
        var convs = settings.settings.conversion;
        
        $('#page').append(
          $('<p>').text('Current conversions:')
        );
        
        if ((convs.convert) && (convs.convert.length() > 0)) {
          var tb = $('<tbody>');
          for (var i in convs.convert) {
            var c = convs.convert[i];
            var tr = $('<tr>').data('convertindex',i);
            tr.append(
              $('<td>').text(c.input)
            ).append(
              $('<td>').text(c.output)
            ).append(
              $('<td>').text(c.encoder)
            );
            var txt = 'No video';
            if (c.video) {
              if (c.video.codec) {
                txt = 'codec: '+c.video.codec;
              }
              else {
                txt = 'codec: current';
              }
              if (c.video.fpks) {
                //is it 1000 frames per sec or frames per 1000 sec?
                txt = txt+', fps: '+c.video.fpks+'000';
              }
              else {
                txt = txt+', fps: default';
              }
              if (c.video.width) {
                txt = txt+', size: '+c.video.width+' by '+c.video.height+'px';
              }
              else {
                txt = txt+', size: current';
              }
            }
            tr.append(
              $('<td>').text(txt)
            );
            var txt = 'No audio';
            if (c.audio) {
              if (c.audio.codec) {
                txt = 'codec: '+c.audio.codec;
              }
              else {
                txt = 'codec: current';
              }
              if (c.audio.samplerate) {
                txt = txt+', samplerate: '+c.audio.samplerate;
              }
              else {
                txt = txt+', samplerate: default';
              }
            }
            tr.append(
              $('<td>').text(txt)
            );
            tb.append(tr);
          }
          $('<table>').append(
            $('<thead>').append(
              $('<tr>').append(
                $('<th>').text('Input file')
              ).append(
                $('<th>').text('Output file')
              ).append(
                $('<th>').text('Encoder')
              ).append(
                $('<th>').text('Video')
              ).append(
                $('<th>').text('Audio')
              )
            )
          ).append(tb);
        }
        else {
          $('#page').append(
            $('<p>').text('None.')
          );
        }
        
        $('#page').append(
          $('<button>').text('Add').click(function(){
            loadSettings(function(){
              showTab('addconversion','new');
            });
          })
        ).append(
          ' '
        ).append(
          $('<button>').text('Clear all').click(function(){
            if(confirmDelete('Are you sure you want to clear all conversions?') == true) {
              convs.clear = true;
              loadSettings();
            }
          })
        );

        break;
      case 'addconversion':
        var c = settings.settings.conversion;
        
        $('#page').append(
            $('<label>').attr('for', 'conv-edit-query').text('Directory').append(
              $('<input>').attr('type', 'text').attr('id', 'conv-edit-query').attr('value','./')
            )
        ).append(
          $('<button>').text('search for input files').click(function(){
            conversionDirQuery($('#conv-edit-query').value);
          })
        ).append(
          $('<div>').attr('id', 'editconversion')
        );
        
        
        $('#editconversion').append(
          $('<label>').attr('for', 'conv-edit-input').text('Input file').append(
            $('<select>').attr('id', 'conv-edit-input').width(237).change(function(){
              //get the input filename, remove the extension, add the dtsc extension
              var filename = $(this).value().split();
              filename.pop();
              filename = filename.join('.');
              filename += '.dtsc';
              $('#conv-edit-output').text(filename);
            })
          )
        ).append(
          $('<label>').attr('for', 'conv-edit-output').text('Output file').append(
            $('<input>').attr('type', 'text').attr('id', 'conv-edit-output')
          )
        ).append(
          $('<label>').attr('for', 'conv-edit-encoder').text('Encoder').append(
            $('<select>').attr('id', 'conv-edit-encoder').width(237)
          )
        ).append(
          $('<label>').attr('for', 'conv-edit-video-codec').text('Video codec').append(
            $('<select>').attr('id', 'conv-edit-video-codec').width(237)
          )
        ).append(
          $('<label>').attr('for', 'conv-edit-video-fps').text('Video fps').append(
            $('<input>').attr('type', 'text').attr('placeholder', 'default').attr('id', 'conv-edit-video-fps')
          )
        ).append(
          $('<label>').attr('for', 'conv-edit-video-fps').text('Video size').append(
            $('<input>').attr('type', 'text').attr('placeholder', 'width').attr('id', 'conv-edit-video-width').width(100)
          ).append(
            $('<span>').text('x').width(13).css('text-align','center')
          ).append(
            $('<input>').attr('type', 'text').attr('placeholder', 'height').attr('id', 'conv-edit-video-height').width(100)
          )
        ).append(
          $('<label>').attr('for', 'conv-edit-audio-codec').text('Audio codec').append(
            $('<select>').attr('id', 'conv-edit-audio-codec').width(237)
          )
        ).append(
          $('<label>').attr('for', 'conv-edit-audio-samplerate').text('Audio samplerate').append(
            $('<input>').attr('type', 'text').attr('placeholder', 'default').attr('id', 'conv-edit-audio-samplerate')
          )
        );
        
        conversionDirQuery('./');
        for (var i in c.encoders) {
          $('#conv-edit-encoder').append(
            $('<option>').value(c.encoders[i])
          );
        }
        //todo: allowed codecs for video/audio
        
        $('#page').append(
          $('<button>').text('Save').click(function(){
            var cobj = {}; //he object we will save
            
            cobj.input = $('#conv-edit-input').value();
            cobj.output =  $('#conv-edit-output').value();
            cobj.encoder =  $('#conv-edit-encoder').value();
            cobj.video.codec =  $('#conv-edit-video-codec').value();
            cobj.video.fpks =  $('#conv-edit-video-fps').value() * 1000; //todo: is this correct?
            cobj.video.width =  $('#conv-edit-video-width').value();
            cobj.video.height =  $('#conv-edit-video-height').value();
            cobj.audio.codec =  $('#conv-edit-audio-codec').value();
            cobj.audio.samplerate =  $('#conv-edit-audio-samplerate').value();
            
            c.convert.push(cobj);
            
            loadSettings(function(){
              showTab('conversion');
            });
          })
        ).append(' ').append(
          $('<button>').text('Cancel').click(function(){
            showTab('conversion');
          })
        );
          
        break;
        
      case 'logs':
        $('#page').append(
          $('<input>').attr('type','checkbox').addClass('logs_refresh')
        ).append(
          $('<span>').text(' Refresh logs every ')
        ).append(
          $('<select>').addClass('logs_refresh_every').append(
            $('<option>').val(10000).text('10 seconds')
          ).append(
            $('<option>').val(30000).text('30 seconds')
          ).append(
            $('<option>').val(60000).text('minute')
          ).append(
            $('<option>').val(300000).text('5 minutes')
          ).append(
            $('<option>').val(600000).text('10 minutes')
          ).append(
            $('<option>').val(1800000).text('30 minutes')
          )
        ).append(
          $('<button>').attr('class', 'floatright').click(function()
          {
            settings.settings.clearstatlogs = 1;
            loadSettings(function()
            {
              showTab('logs');
            });
          }).text('Purge logs')
        ).append(
          buildLogsTable()
        );
        
        $('.logs_refresh').change(function(){
          if ($(this).is(':checked')) {
            var delay = $('.logs_refresh_every').val();
            logsinterval = setInterval(function(){getLogsdata();},delay);
            getLogsdata();
          }
          else {
            clearInterval(logsinterval);
          }
        });
        $('.logs_refresh_every').change(function(){
          if ($('.logs_refresh').is(':checked')) {
            var delay = $(this).val();
            clearInterval(logsinterval);
            logsinterval = setInterval(function(){getLogsdata();},delay);
          }
        });
        
        break;
        
      case 'server stats':
        loadSettings(function(){
          serverstats = settings.settings.capabilities;
          
          if (serverstats.cpu !== undefined) 
          {
            $('#page').append(
              $('<div>').attr('class','datacont').append(
                $('<p>').text('CPU')
              )
            );
            //be careful, only works if this is the first div to be constructed
            for (property in serverstats.cpu[0]) 
            {
              $('#page div.datacont').append(
                $('<label>').text(property).append(
                  $('<span>').text(serverstats.cpu[0][property])
                )
              );
            }
          }
          if (serverstats.mem !== undefined) 
          {
            $('#page').append(
              $('<div>').attr('class','datacont').append(
                $('<p>').text('Memory')
              ).append(
                $('<label>').text('Physical memory').append(
                  $('<span>').text(serverstats.mem.used+'MiB/'+serverstats.mem.total+'MiB ('+serverstats.mem.free+'MiB available)')
                )
              ).append(
                $('<label>').text('Swap memory').append(
                  $('<span>').text((serverstats.mem.swaptotal - serverstats.mem.swapfree)+'MiB/'+serverstats.mem.swaptotal+'MiB ('+serverstats.mem.swapfree+'MiB available)')
                )
              )								
            );
          }
          if (serverstats.load !== undefined) 
          {
            $('#page').append(
              $('<div>').attr('class','datacont').append(
                $('<p>').text('Load')
              ).append(
                $('<label>').text('Memory used').append(
                  $('<span>').text(serverstats.load.memory+'%')
                )
              ).append(
                $('<label>').text('Loading averages').append(
                  $('<span>').text('1 min: '+serverstats.load.one+'%, 5 min: '+serverstats.load.five+'%, 15 min: '+serverstats.load.fifteen+'%')
                )
              )
            );
          }
        });
        
        break;
      
      case 'disconnect':
        showTab('login');
        setHeaderState('disconnected');
        $('#nav').css('visibility', 'hidden');
        
        settings =
        {
          server: '',
          credentials:
          {
            username: "",
            password: "",
            authstring: ""
          },
          settings: {}
        };
        break;
    }  // end switch
    
    //placeholder for older browsers
    $('input[placeholder]').placeholder();
    
    if (settings.settings.LTS != 1) {
      $('.LTS-only input').add('.LTS-only select').add('.LTS-only button').attr('disabled','disabled');
      $('.LTS-only').hover(function(e){
        removeTooltip();
        showTooltip(e,undefined,'This is feature is only available in the LTS version.');
      },function(){
        removeTooltip();
      });
      
      $('.LTS-only').add('.LTS-only p').add('.LTS-only label').add('.LTS-only button').css('color','#b4b4b4');
    }
  }