<!doctype html>

<html lang='en'>

   <head>

      <meta charset='utf-8' />

      <title>Server Manager - not connected</title>

      <script src='jquery.js'></script><!-- TODO inline -->
      <script>var MD5=function(j){function RotateLeft(a,b){return(a<<b)|(a>>>(32-b))}function AddUnsigned(a,b){var c,lY4,lX8,lY8,lResult;lX8=(a&0x80000000);lY8=(b&0x80000000);c=(a&0x40000000);lY4=(b&0x40000000);lResult=(a&0x3FFFFFFF)+(b&0x3FFFFFFF);if(c&lY4){return(lResult^0x80000000^lX8^lY8)}if(c|lY4){if(lResult&0x40000000){return(lResult^0xC0000000^lX8^lY8)}else{return(lResult^0x40000000^lX8^lY8)}}else{return(lResult^lX8^lY8)}}function F(x,y,z){return(x&y)|((~x)&z)}function G(x,y,z){return(x&z)|(y&(~z))}function H(x,y,z){return(x^y^z)}function I(x,y,z){return(y^(x|(~z)))}function FF(a,b,c,d,x,s,e){a=AddUnsigned(a,AddUnsigned(AddUnsigned(F(b,c,d),x),e));return AddUnsigned(RotateLeft(a,s),b)};function GG(a,b,c,d,x,s,e){a=AddUnsigned(a,AddUnsigned(AddUnsigned(G(b,c,d),x),e));return AddUnsigned(RotateLeft(a,s),b)};function HH(a,b,c,d,x,s,e){a=AddUnsigned(a,AddUnsigned(AddUnsigned(H(b,c,d),x),e));return AddUnsigned(RotateLeft(a,s),b)};function II(a,b,c,d,x,s,e){a=AddUnsigned(a,AddUnsigned(AddUnsigned(I(b,c,d),x),e));return AddUnsigned(RotateLeft(a,s),b)};function ConvertToWordArray(a){var b;var c=a.length;var d=c+8;var e=(d-(d%64))/64;var f=(e+1)*16;var g=Array(f-1);var h=0;var i=0;while(i<c){b=(i-(i%4))/4;h=(i%4)*8;g[b]=(g[b]|(a.charCodeAt(i)<<h));i++}b=(i-(i%4))/4;h=(i%4)*8;g[b]=g[b]|(0x80<<h);g[f-2]=c<<3;g[f-1]=c>>>29;return g};function WordToHex(a){var b="",WordToHexValue_temp="",lByte,lCount;for(lCount=0;lCount<=3;lCount++){lByte=(a>>>(lCount*8))&255;WordToHexValue_temp="0"+lByte.toString(16);b=b+WordToHexValue_temp.substr(WordToHexValue_temp.length-2,2)}return b};function Utf8Encode(a){a=a.replace(/\r\n/g,"\n");var b="";for(var n=0;n<a.length;n++){var c=a.charCodeAt(n);if(c<128){b+=String.fromCharCode(c)}else if((c>127)&&(c<2048)){b+=String.fromCharCode((c>>6)|192);b+=String.fromCharCode((c&63)|128)}else{b+=String.fromCharCode((c>>12)|224);b+=String.fromCharCode(((c>>6)&63)|128);b+=String.fromCharCode((c&63)|128)}}return b};var x=Array();var k,AA,BB,CC,DD,a,b,c,d;var l=7,S12=12,S13=17,S14=22;var m=5,S22=9,S23=14,S24=20;var o=4,S32=11,S33=16,S34=23;var p=6,S42=10,S43=15,S44=21;j=Utf8Encode(j);x=ConvertToWordArray(j);a=0x67452301;b=0xEFCDAB89;c=0x98BADCFE;d=0x10325476;for(k=0;k<x.length;k+=16){AA=a;BB=b;CC=c;DD=d;a=FF(a,b,c,d,x[k+0],l,0xD76AA478);d=FF(d,a,b,c,x[k+1],S12,0xE8C7B756);c=FF(c,d,a,b,x[k+2],S13,0x242070DB);b=FF(b,c,d,a,x[k+3],S14,0xC1BDCEEE);a=FF(a,b,c,d,x[k+4],l,0xF57C0FAF);d=FF(d,a,b,c,x[k+5],S12,0x4787C62A);c=FF(c,d,a,b,x[k+6],S13,0xA8304613);b=FF(b,c,d,a,x[k+7],S14,0xFD469501);a=FF(a,b,c,d,x[k+8],l,0x698098D8);d=FF(d,a,b,c,x[k+9],S12,0x8B44F7AF);c=FF(c,d,a,b,x[k+10],S13,0xFFFF5BB1);b=FF(b,c,d,a,x[k+11],S14,0x895CD7BE);a=FF(a,b,c,d,x[k+12],l,0x6B901122);d=FF(d,a,b,c,x[k+13],S12,0xFD987193);c=FF(c,d,a,b,x[k+14],S13,0xA679438E);b=FF(b,c,d,a,x[k+15],S14,0x49B40821);a=GG(a,b,c,d,x[k+1],m,0xF61E2562);d=GG(d,a,b,c,x[k+6],S22,0xC040B340);c=GG(c,d,a,b,x[k+11],S23,0x265E5A51);b=GG(b,c,d,a,x[k+0],S24,0xE9B6C7AA);a=GG(a,b,c,d,x[k+5],m,0xD62F105D);d=GG(d,a,b,c,x[k+10],S22,0x2441453);c=GG(c,d,a,b,x[k+15],S23,0xD8A1E681);b=GG(b,c,d,a,x[k+4],S24,0xE7D3FBC8);a=GG(a,b,c,d,x[k+9],m,0x21E1CDE6);d=GG(d,a,b,c,x[k+14],S22,0xC33707D6);c=GG(c,d,a,b,x[k+3],S23,0xF4D50D87);b=GG(b,c,d,a,x[k+8],S24,0x455A14ED);a=GG(a,b,c,d,x[k+13],m,0xA9E3E905);d=GG(d,a,b,c,x[k+2],S22,0xFCEFA3F8);c=GG(c,d,a,b,x[k+7],S23,0x676F02D9);b=GG(b,c,d,a,x[k+12],S24,0x8D2A4C8A);a=HH(a,b,c,d,x[k+5],o,0xFFFA3942);d=HH(d,a,b,c,x[k+8],S32,0x8771F681);c=HH(c,d,a,b,x[k+11],S33,0x6D9D6122);b=HH(b,c,d,a,x[k+14],S34,0xFDE5380C);a=HH(a,b,c,d,x[k+1],o,0xA4BEEA44);d=HH(d,a,b,c,x[k+4],S32,0x4BDECFA9);c=HH(c,d,a,b,x[k+7],S33,0xF6BB4B60);b=HH(b,c,d,a,x[k+10],S34,0xBEBFBC70);a=HH(a,b,c,d,x[k+13],o,0x289B7EC6);d=HH(d,a,b,c,x[k+0],S32,0xEAA127FA);c=HH(c,d,a,b,x[k+3],S33,0xD4EF3085);b=HH(b,c,d,a,x[k+6],S34,0x4881D05);a=HH(a,b,c,d,x[k+9],o,0xD9D4D039);d=HH(d,a,b,c,x[k+12],S32,0xE6DB99E5);c=HH(c,d,a,b,x[k+15],S33,0x1FA27CF8);b=HH(b,c,d,a,x[k+2],S34,0xC4AC5665);a=II(a,b,c,d,x[k+0],p,0xF4292244);d=II(d,a,b,c,x[k+7],S42,0x432AFF97);c=II(c,d,a,b,x[k+14],S43,0xAB9423A7);b=II(b,c,d,a,x[k+5],S44,0xFC93A039);a=II(a,b,c,d,x[k+12],p,0x655B59C3);d=II(d,a,b,c,x[k+3],S42,0x8F0CCC92);c=II(c,d,a,b,x[k+10],S43,0xFFEFF47D);b=II(b,c,d,a,x[k+1],S44,0x85845DD1);a=II(a,b,c,d,x[k+8],p,0x6FA87E4F);d=II(d,a,b,c,x[k+15],S42,0xFE2CE6E0);c=II(c,d,a,b,x[k+6],S43,0xA3014314);b=II(b,c,d,a,x[k+13],S44,0x4E0811A1);a=II(a,b,c,d,x[k+4],p,0xF7537E82);d=II(d,a,b,c,x[k+11],S42,0xBD3AF235);c=II(c,d,a,b,x[k+2],S43,0x2AD7D2BB);b=II(b,c,d,a,x[k+9],S44,0xEB86D391);a=AddUnsigned(a,AA);b=AddUnsigned(b,BB);c=AddUnsigned(c,CC);d=AddUnsigned(d,DD)}var q=WordToHex(a)+WordToHex(b)+WordToHex(c)+WordToHex(d);return q.toLowerCase()};</script>

      <style>

body
{
   background-color: #fafafa;
   margin: 0;
}

#page
{
   overflow: hidden;
   margin: 10px -170px 0 230px;
   padding: 0;   
}



/* content - tables */

table
{
   width: 100%;
   margin-top: 5px;
   border-spacing: 0;
}

table thead
{
   background-color: #c8c8c8;
}

table th, table td
{
   height: 30px;
   padding: 0 0 0 30px;
}

table th
{
   color: #505050;
   text-align: left;
}

table td
{
   color: #505050;
}

tbody tr:nth-child(even)
{
   background-color: #f0f0f0;
}
tbody tr:nth-child(odd)
{
   background-color: #f3f3f3;
}




/* login stuff */

#login
{
   width: 250px;
}

#login > input
{
   display: block;
   margin: 5px 0 13px 0;
   width: 240px;
}

/* connect button */

#login > button
{
   float: right;
   margin: 0;
}



/* input general */
input, select
{
   padding: 5px;
   color: #505050;
   border: 1px solid #b4b4b4;
}

button
{
   height: 30px;
   background-color: #505050;
   color: #fff;
   border: 0;
}


tbody button,
tbody select,
tbody input
{
   padding: 2px;
   height: 22px;
}

tbody td button
{
   padding: 2px 7px 2px 7px;
}

tbody td.center
{
   text-align: center;
}







/* header */

#header
{
   margin: 30px 0 0 0;
   width: 100%;
   background-color: #b4b4b4;
   height: 30px;
}

#header-title
{
   padding: 0 0 0 30px;
   float: left;
}

#header-status
{
   float: right;
   padding: 0 30px 0 0;
}

#header-title, #header-status
{
   line-height: 30px;
}

.disconnected
{
   color: #cc3333;
}

.connected
{
   color: #14991a;
}

.loggingin
{
   color: #ee8833;
}

#header
{
   color: #fafafa;
}



/* navigation */

#nav
{
   float: left;
   width: 200px;
   list-style: none;
   padding: 0;
   margin: 10px 0 0 0;
}

#nav li
{
   display: block;
   color: #b4b4b4;
   line-height: 30px;
   padding: 0 0 0 30px;
   margin: 5px 0 5px 0;
   cursor: pointer;
}

#nav li:hover, #nav .selected
{
   color: #505050;
   background-color: #c8c8c8;
}

#nav #logoutbutton
{
   color: #cc3333;
}




/* fonts */

#header-title > span, #header-connection, #header-host,
#nav,
th,
p,
label
{
   font: normal bold 11pt Arial, sans-serif;
   text-transform: uppercase;
}

#login > input, #login > button
{
   font: normal bold 11pt Arial, sans-serif;
}


td
{
   font: normal normal 10pt Arial, sans-serif;
}

      </style>


   </head>

   <body>

      <div id='header'>

         <div id='header-title'>
            <span>Mistserver Manager</span>
         </div>

         <div id='header-status'>
            <span id='header-connection' class='disconnected'>Disconnected</span>
            <span id='header-host'></span>
         </div>

      </div>

      <ul id='nav'>
         <li class='selected'>overview</li>
         <li>protocols</li>
         <li>streams</li>
         <li>limits</li>
         <li>logs</li>
         <li id='logoutbutton'>disconnect</li>
      </ul>

      <div id='page'></div>

   </body>

   <script>

      // creds and local copy of the settings
      var settings =
      {
         server: '',
         credentials:
         {
            username: "",
            password: "",
            authstring: ""
         },
         settings: {}
      };

      var ltypes =
      [
         ['kb_total', 'Total bandwidth'],
         ['kbps_max', 'Current bandwidth'],
         ['users', 'Concurrent users'],
         ['streams', 'Cocurrent streams'],
         ['geo', 'Geolimited'],
         ['host', 'Hostlimited'],
         ['time', 'Timelimited'],
         ['duration', 'Duration'],
         ['str_kbps_min', 'Minimum bitrate'],
         ['str_kbps_max', 'Maximum bitrate']
      ];

      $(document).ready(function()
      {
         $('#nav').children().each(function()
         {
            $(this).click(function()
            {
               // remove currently selected
               $('#nav').children().each(function()
               {
                  $(this).attr('class', '');
               });
               // select this one
               $(this).attr('class', 'selected');
               // show correct tab
               showTab($(this).text());
            });
         });

         // onload show login 'tab' and hide menu
         showTab('login');
         $('#nav').css('visibility', 'hidden');
      });


      // format date to something pretty
      function formatDate(date)
      {
         var d = new Date(date * 1000);

         return [
            ('00' + d.getMonth()).slice(-2),
            ('00' + d.getDate()).slice(-2),
            d.getFullYear()
         ].join('/') + ' ' + [
            ('00' + d.getHours()).slice(-2),
            ('00' + d.getMinutes()).slice(-2),
            ('00' + d.getSeconds()).slice(-2)
         ].join(':');
      }


      function shortToLongLimit(name)
      {
         console.log('getting the long name for the limit "' + name + '"');

         var i;

         for(i = 0; i < ltypes.length; i++)
         {
            if(name == ltypes[i][0])
            {
               return ltypes[i][1];
            }
         }

         console.log('ERROR! short limit ', name, ' not in list, returning _short name_!');
         return name;
      }


      // connect to server and set/get settings
      function loadSettings(callback)
      {
         var errorstr = '',
             data = $.extend(settings.settings,
             {
                'authorize':
                {
                   'username': settings.credentials.username,
                   'password': MD5(MD5(settings.credentials.password) + settings.credentials.authstring)
                }
             });

         console.log('SEND', data);

         $.ajax(
         {
            'url': settings.server,
            'data':
            {
               "command": JSON.stringify(data)
            },
            'dataType': 'jsonp',
            'timeout': 2500,
            'error': function()
            {
               setHeaderState('disconnected');
            },
            'success': function(d)
            {
               console.log('RECV', d);

               if(d && d['authorize'] && d['authorize']['challenge'])
               {
                  if (settings.credentials.authstring != d['authorize']['challenge'])
                  {
                     settings.credentials.authstring = d['authorize']['challenge'];
                     console.log('need to reload settings with new auth string');
                     loadSettings(callback);
                     return;
                  }else{
                     errorstr = 'wrong credentials';
                  }
               }else{
                  settings.settings = $.extend(true, {
                     "config":
                     {
                        "host": "",
                        "limits": [],
                        "name": "",
                        "protocols": {},
                        "status": "",
                        "version": ""
                     },
                     "streams": {},
                     "log": {},
                     "statistics": {}
                  }, d);

                  console.log('new (shinyness) object:', settings.settings);
               }

               if(callback)
               {
                  callback(errorstr);
               }
            }
         });
      }



      function setHeaderState(state)
      {
         var text, cname, title;

         switch(state)
         {
            case 'logingin':        text = 'connecting...';    cname = 'loggingin';       title = 'connecting to ' + settings.server;     break;
            case 'disconnected':    text = 'disconnected';     cname = 'disconnected';    title = 'disconnected';                         break;
            case 'connected':       text = 'connected';        cname = 'connected';       title = 'connected to ' + settings.server;      break;
         }

         document.title = 'Server Manager - ' + title;

         $('#header-connection').attr('class', cname);
         $('#header-connection').text(text);
         $('#header-host').text(settings.server.replace('http://', ''));
      }





      // show tab
      function showTab(name)
      {
         // clear page
         $('#page').html('');

         switch(name)
         {
            case 'login':

//TODO fixme login creds
               var host = $('<input>').attr('type', 'text').attr('placeholder', 'http://localhost:4242');
               var user = $('<input>').attr('type', 'text').attr('placeholder', 'USERNAME');/*.attr('value', 'testaccount'); */
               var pass = $('<input>').attr('type', 'password').attr('placeholder', 'PASSWORD');/*.attr('value', 'pisvlek'); */
               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');

                  // 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');
                           }
                        });

                        console.log('logged in!');
                     }else{
                        setHeaderState('disconnected');
                        $('#header-host').text('');
                        console.log('error logging in: ' + errorstr);
                     }
                  });
               }).text('connect');

               $('#page').append(
                  $('<div>').attr('id', 'login').append(host).append(user).append(pass).append(conn)
               );
               break;




            case 'overview':

               $('#page').append($('<p>').text('TODO overview'));

               break;




            case 'protocols':

               $table = $('<table>');
               $table.html("<thead><th>Protocol</th><th>Port</th><th></th></thead>");
               $tbody = $('<tbody>');

               var tr, protocol;

               // remove old stuff
               $tbody.html('');

               for(protocol in settings.settings.config.protocols)
               {
                  tr = $('<tr>').attr('id', 'protocol-' + protocol);

                  tr.append( $('<td>').text( protocol ) );
                  tr.append( $('<td>').text( settings.settings.config.protocols[protocol].port ) );

                  tr.append( $('<td>').attr('class', 'center').append( $('<button>').click(function()
                             {
                                var id = $(this).parent().attr('id').replace('protocol-', '');
                                delete settings.settings.config.protocols[protocol];
                                $(this).parent().parent().remove();
                                loadSettings();
                             }).text('delete') ) );

                  $tbody.append(tr);
               }


               // add new limit!
               $nprot = $('<tr>');
               // protocol select
               $pname = $('<select>').attr('id', 'new-protocol-name');
               $pname.append( $('<option>').attr('value', 'HTTP').text('HTTP') );
               $pname.append( $('<option>').attr('value', 'RTMP').text('RTMP') );

               $nprot.append( $('<td>').append($pname) );
               // val
               $nprot.append( $('<td>').append( $('<input>').attr('type', 'text').attr('id', 'new-protocol-val') ) );

               $nprot.append(
                  $('<td>').attr('class', 'center').append(
                     $('<button>').click(function()
                     {
                        settings.settings.config.protocols[$('#new-protocol-name :selected').val()] =
                        {
                           port: $('#new-protocol-val').val()
                        };

                        loadSettings(function()
                        {
                           showTab('protocols');
                        });

                     }).text('add new')
                  )
               );

               $tbody.append($nprot);
               $table.append($tbody);
               $('#page').append($table);

               break;







            case 'streams':

               $streamselector = $('<select>').attr('id', 'streams-selector');

               $streamselector.append( $('<option>').attr('disabled', 'disabled').text('Select a stream...') );

               for(stream in settings.settings.streams)
               {
                  $streamselector.append( $('<option>').attr('value', stream).text(settings.settings.streams[stream].name) );
               }

               $streamselector.change(function()
               {
                  var sname = $('#streams-selector :selected').val();
                  var stream = settings.settings.streams[sname];

$('#page').append( $('<p>').text('TODO stream settings: ' + sname + ' / ' + stream) );
/* // TODO
                  $('#page').append( $('<label>').attr('for', 'stream-name').text('Name').append( $('<input>').attr('id', 'stream-name').attr('value', stream.name) ) );
                  $('#page').append( $('<label>').attr('for', 'stream-group').text('Group').append( $('<input>').attr('id', 'stream-group').attr('value', stream.group) ) );

                  $('#page').append(
                     $('<div>').text('Channel').append(
                        $('<label>').attr('for', 'stream-channel-url').text('URL').append( $('<input>').attr('id', 'stream-channel-url').attr('value', stream.channel.URL) )
                     ).append(
                        $('<label>').attr('for', 'stream-channel-account').text('Account').append( $('<input>').attr('id', 'stream-channel-account').attr('value', stream.channel.account) )
                     )
                  );
*/

               });

               $('#page').append( $streamselector );

               break;










            case 'limits':
               $table = $('<table>');
               $table.html("<thead><th>Type</th><th>Hard/soft limit</th><th>Value</th><th></th></thead>");
               $tbody = $('<tbody>');

               var i, tr, limit,
                   len = settings.settings.config.limits.length;

               // remove old stuff
               $tbody.html('');

               for(i = 0; i < len; i++)
               {
                  tr = $('<tr>').attr('id', 'limits-' + i);
                  limit = settings.settings.config.limits[i];

                  tr.append( $('<td>').text( shortToLongLimit(limit.name) ) );
                  tr.append( $('<td>').text( limit.type ) );
                  tr.append( $('<td>').text( limit.val ) );

                  tr.append( $('<td>').attr('class', 'center').append( $('<button>').click(function()
                             {
                                var id = $(this).parent().attr('id').replace('limits-', '');
                                settings.settings.config.limits.splice(id, 1);
                                $(this).parent().parent().remove();

                                loadSettings();
                             }).text('delete') ) );

                  $tbody.append(tr);
               }

               // add new limit!
               $nltr = $('<tr>');

               // type select
               $ltype = $('<select>').attr('id', 'new-limit-type');
               for(i = 0; i < ltypes.length; i++)
               {
                  $ltype.append( $('<option>').attr('value', ltypes[i][0]).text(ltypes[i][1]) );
               }
               $nltr.append( $('<td>').append( $ltype ) );
               // hard/soft
               $nltr.append( $('<td>').append( $('<select>').attr('id', 'new-limit-hs').append( $('<option>').attr('value', 'hard').text('Hard limit') ).append( $('<option>').attr('value', 'soft').text('Soft limit') ) ) );
               // val
               $nltr.append( $('<td>').append( $('<input>').attr('type', 'text').attr('id', 'new-limit-val') ) );

               $nltr.append(
                  $('<td>').attr('class', 'center').append(
                     $('<button>').click(function()
                     {
                        settings.settings.config.limits.push(
                        {
                           name: $('#new-limit-type :selected').val(),
                           type: $('#new-limit-hs :selected').val(),
                           val:  $('#new-limit-val').val()
                        });

                        loadSettings(function()
                        {
                           showTab('limits');
                        });

                     }).text('add new')
                  )
               );
               $tbody.append($nltr);

               $table.append($tbody);
               $('#page').append($table);

               break;





            case 'logs':
               $table = $('<table>');
               $table.html("<thead><th>Date</th><th>Type</th><th>Message</th></thead>");
               $tbody = $('<tbody>');

               var i, cur, $tr,
                   logs = settings.settings.log,
                   len = logs.length;

               if(len >= 2 && settings.settings.log[0][0] < settings.settings.log[len - 1][0])
               {
                  logs.reverse();
               }

               $tbody.html('');

               for(i = 0; i < len; i++)
               {
                  cur = settings.settings.log[i];

                  $tr = $('<tr>').append(
                     $('<td>').text(formatDate(cur[0]))
                  ).append(
                     $('<td>').text(cur[1])
                  ).append(
                     $('<td>').text(cur[2])
                  );

                  $tbody.append($tr);
               }

               $table.append($tbody);
               $('#page').append($table);

               break;





            case 'disconnect':
               showTab('login');
               setHeaderState('disconnected');
               $('#nav').css('visibility', 'hidden');

               settings =
               {
                  server: '',
                  credentials:
                  {
                     username: "",
                     password: "",
                     authstring: ""
                  },
                  settings: {}
               };
               break;
         }
      }

   </script>

</html>