<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Droid Controller Application</title>

  <script src="https://media.twiliocdn.com/sdk/js/sync/v0.7/twilio-sync.js"></script>
  <script src="https://media.twiliocdn.com/sdk/js/common/v0.1/twilio-common.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jQuery-Knob/1.2.13/jquery.knob.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/nipplejs/0.6.7/nipplejs.min.js"></script>
  <script>

    function getToken() {
      return new Promise((resolve, reject) => {
        const request = window.superagent;
        $.getJSON('/token', data => {
          console.log('Got token for identity:', data.identity);
          resolve(data.token);
        });
      });
    }

    window.onload = () => {

      $(".leftMotor").knob();
      $(".rightMotor").knob();
      $(".proximity").knob();

      getToken()
        .then(token => {

          let syncClient = new Twilio.Sync.Client(token);
          let accessManager = new Twilio.AccessManager(token);
          accessManager.on('tokenExpired', () => {
            getToken().then(t => {
              accessManager.updateToken(t);
            });
          });
          return { client: syncClient, manager: accessManager };
        })
        .then(c => {
          c.client.document('motors').then(doc => {
            c.manager.on('tokenUpdated', am => {
              console.log('Token updated:', am);
              c.client.updateToken(am.token);
            });

            doc.on('updated', args => {
              $(".leftMotor").val(-args.value.l1).trigger('change');
              $(".rightMotor").val(-args.value.l2).trigger('change');
            });

            nipplejs.create({
              zone: document.getElementById('joystick'),
              color: 'blue',
              size: 300
            }).on('added', (evt, nipple) => {
                nipple.on('move', (evt, data) => {
                  let dx = data.position.x - nipple.position.x;
                  let dy = data.position.y - nipple.position.y;
                  let leftMotor = Math.round(dy + dx);
                  let rightMotor = Math.round(dy - dx);
                  console.debug('Motors:', leftMotor, rightMotor);
                  doc.set({ l1: leftMotor, l2: rightMotor });
              	});
            }).on('removed', (evt, nipple) => {
                nipple.off('move');
                doc.set({ l1: 0, l2: 0 });
            });
          });
          c.client.stream('sensors').then(stream => {
            stream.on('messagePublished', args => {
              console.debug('Sensors:', args.message.value);
              $(".proximity").val(args.message.value.ir).trigger('change');
            });
          });
        })
        .catch(error => {
          console.error("Failed initializing: ", error);
        });
    };
  </script>
</head>

<body>
  <div class="dials" align="center" style="margin-top: 20px">
    <input class="leftMotor" data-width="150" data-height="150" data-min="-300" data-max="300" data-fgColor="#0000ff" value="0" readonly>
    <input class="rightMotor" data-width="150" data-height="150" data-min="-300" data-max="300" data-fgColor="#0000ff" value="0" readonly>
    <input class="proximity" data-width="150" data-height="150" data-min="0" data-max="100" data-fgColor="#ff0000" value="0" readonly>
  </div>
  <div class="controls" align="center" style="margin-top: 20px">
    <div id="joystick" style="background: #eeeeee; position: relative; width: 500px; height: 500px; border: 1px solid #aaaaaa;">
      Control stick pad
    </div>
  </div>
</body>
</html>