// META: script=/resources/testdriver.js
// META: script=/resources/testharnessreport.js
'use strict'

var base_uuid = '00000000-0000-1000-8000-00805f9b34fb'

test(() => {
  let base_alias = 0x0
  assert_equals(BluetoothUUID.getService(base_alias), base_uuid);
  assert_equals(BluetoothUUID.getCharacteristic(base_alias), base_uuid);
  assert_equals(BluetoothUUID.getDescriptor(base_alias), base_uuid);
}, '0x0 should produce valid UUID.');

test(() => {
  assert_equals(BluetoothUUID.getService(NaN), base_uuid);
  assert_equals(BluetoothUUID.getCharacteristic(NaN), base_uuid);
  assert_equals(BluetoothUUID.getDescriptor(NaN), base_uuid);
}, 'NaN returns basic uuid');

test(
    () => {
      let max_uuid = 'ffffffff-0000-1000-8000-00805f9b34fb';
      let nine_digits = 0xfffffffff;
      let thirteen_digits = 0xfffffffffffff;
      let fourteen_digits = 0xffffffffffffff;
      assert_equals(BluetoothUUID.getService(nine_digits), max_uuid);
      assert_equals(BluetoothUUID.getCharacteristic(nine_digits), max_uuid);
      assert_equals(BluetoothUUID.getDescriptor(nine_digits), max_uuid);
      assert_equals(BluetoothUUID.getService(thirteen_digits), max_uuid);
      assert_equals(BluetoothUUID.getCharacteristic(thirteen_digits), max_uuid);
      assert_equals(BluetoothUUID.getDescriptor(thirteen_digits), max_uuid);
      assert_equals(BluetoothUUID.getService(fourteen_digits), base_uuid);
      assert_equals(
          BluetoothUUID.getCharacteristic(fourteen_digits), base_uuid);
      assert_equals(BluetoothUUID.getDescriptor(fourteen_digits), base_uuid);
    },
    'Values between 0xfffffffff (8 digits) and 0xffffffffffffff (14 digits)' +
        'should return max UUID');

test(() => {
  assert_equals(BluetoothUUID.getService(Infinity), base_uuid);
  assert_equals(BluetoothUUID.getCharacteristic(Infinity), base_uuid);
  assert_equals(BluetoothUUID.getDescriptor(Infinity), base_uuid);
}, 'Infinity returns base UUID');

test(() => {
  let deadbeef_alias = 0xDEADBEEF;
  let deadbeef_uuid = 'deadbeef-0000-1000-8000-00805f9b34fb';
  assert_equals(BluetoothUUID.getService(deadbeef_alias), deadbeef_uuid);
  assert_equals(BluetoothUUID.getCharacteristic(deadbeef_alias), deadbeef_uuid);
  assert_equals(BluetoothUUID.getDescriptor(deadbeef_alias), deadbeef_uuid);
}, '0xdeadbeef should produce valid UUID.');

test(() => {
  let adeadbeef_alias = 0xADEADBEEF;
  let adeadbeef_uuid = 'deadbeef-0000-1000-8000-00805f9b34fb';
  assert_equals(BluetoothUUID.getService(adeadbeef_alias), adeadbeef_uuid);
  assert_equals(
      BluetoothUUID.getCharacteristic(adeadbeef_alias), adeadbeef_uuid);
  assert_equals(BluetoothUUID.getDescriptor(adeadbeef_alias), adeadbeef_uuid);
}, 'Only first 32bits should be used.');

test(() => {
  let basic_uuid = '1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d';
  assert_equals(BluetoothUUID.getService(basic_uuid), basic_uuid);
  assert_equals(BluetoothUUID.getCharacteristic(basic_uuid), basic_uuid);
  assert_equals(BluetoothUUID.getDescriptor(basic_uuid), basic_uuid);
}, 'A valid UUID String should return the same UUID.');

test(() => {
  let all_caps_uuid = '1A2B3C4D-5E6F-7A8B-9C0D-1E2F3A4B5C6D';
  assert_throws_js(TypeError, () => BluetoothUUID.getService(all_caps_uuid));
  assert_throws_js(
      TypeError, () => BluetoothUUID.getCharacteristic(all_caps_uuid));
  assert_throws_js(TypeError, () => BluetoothUUID.getDescriptor(all_caps_uuid));
}, 'A UUID String with uppercase letters is an invalid UUID.');

test(() => {
  let string_alias = 'deadbeef';
  assert_throws_js(TypeError, () => BluetoothUUID.getService(string_alias));
  assert_throws_js(
      TypeError, () => BluetoothUUID.getCharacteristic(string_alias));
  assert_throws_js(TypeError, () => BluetoothUUID.getDescriptor(string_alias));
}, 'A 32bit *String* alias is invalid.');

test(() => {
  let invalid_character_uuid = '0000000g-0000-1000-8000-00805f9b34fb';
  assert_throws_js(
      TypeError, () => BluetoothUUID.getService(invalid_character_uuid));
  assert_throws_js(
      TypeError,
      () => BluetoothUUID.getCharacteristic(invalid_character_uuid));
  assert_throws_js(
      TypeError, () => BluetoothUUID.getDescriptor(invalid_character_uuid));
}, 'A UUID with invalid characters is an invalid UUID.');

test(() => {
  assert_equals(
      BluetoothUUID.getService('alert_notification'),
      '00001811-0000-1000-8000-00805f9b34fb');
  assert_equals(
      BluetoothUUID.getCharacteristic('aerobic_heart_rate_lower_limit'),
      '00002a7e-0000-1000-8000-00805f9b34fb');
  assert_equals(
      BluetoothUUID.getDescriptor('gatt.characteristic_extended_properties'),
      '00002900-0000-1000-8000-00805f9b34fb');
}, 'A valid UUID from a name.');

test(() => {
  assert_throws_js(TypeError, () => {
    BluetoothUUID.getService('aerobic_heart_rate_lower_limit');
  });
  assert_throws_js(TypeError, () => {
    BluetoothUUID.getService('gatt.characteristic_extended_properties');
  });
  assert_throws_js(TypeError, () => {
    BluetoothUUID.getCharacteristic('alert_notification');
  });
  assert_throws_js(TypeError, () => {
    BluetoothUUID.getCharacteristic('gatt.characteristic_extended_properties');
  });
  assert_throws_js(TypeError, () => {
    BluetoothUUID.getDescriptor('alert_notification');
  });
  assert_throws_js(TypeError, () => {
    BluetoothUUID.getDescriptor('aerobic_heart_rate_lower_limit');
  });
}, 'Make sure attributes don\'t share a map');

test(() => {
  let wrong_name = 'wrong_name';
  assert_throws_js(TypeError, () => BluetoothUUID.getService(wrong_name));
  assert_throws_js(TypeError, () => BluetoothUUID.getCharacteristic(wrong_name));
  assert_throws_js(TypeError, () => BluetoothUUID.getDescriptor(wrong_name));
}, 'Invalid Descriptor name');

test(() => {
  let object = {};
  let array = [];
  let func = () => {};

  // cannonicalUUID
  assert_throws_js(TypeError, () => BluetoothUUID.canonicalUUID(object));
  // [] converts to '', which converts to 0 before the range check.
  assert_equals(BluetoothUUID.canonicalUUID(array), base_uuid);
  assert_throws_js(TypeError, () => BluetoothUUID.canonicalUUID(func));
  assert_throws_js(TypeError, () => BluetoothUUID.canonicalUUID(undefined));
  assert_equals(BluetoothUUID.canonicalUUID(null), base_uuid);
  assert_equals(BluetoothUUID.canonicalUUID(false), base_uuid);
  assert_equals(
      BluetoothUUID.canonicalUUID(true), BluetoothUUID.canonicalUUID(1));
  assert_throws_js(TypeError, () => BluetoothUUID.canonicalUUID(NaN));

  // getService
  assert_throws_js(TypeError, () => BluetoothUUID.getService(object));
  assert_throws_js(TypeError, () => BluetoothUUID.getService(array));
  assert_throws_js(TypeError, () => BluetoothUUID.getService(func));
  assert_throws_js(TypeError, () => BluetoothUUID.getService(undefined));
  assert_throws_js(TypeError, () => BluetoothUUID.getService(null));
  assert_throws_js(TypeError, () => BluetoothUUID.getService(false));

  // getCharacteristic
  assert_throws_js(TypeError, () => BluetoothUUID.getCharacteristic(object));
  assert_throws_js(TypeError, () => BluetoothUUID.getCharacteristic(array));
  assert_throws_js(TypeError, () => BluetoothUUID.getCharacteristic(func));
  assert_throws_js(TypeError, () => BluetoothUUID.getCharacteristic(undefined));
  assert_throws_js(TypeError, () => BluetoothUUID.getCharacteristic(null));
  assert_throws_js(TypeError, () => BluetoothUUID.getCharacteristic(false));

  // getDescriptor
  assert_throws_js(TypeError, () => BluetoothUUID.getDescriptor(object));
  assert_throws_js(TypeError, () => BluetoothUUID.getDescriptor(array));
  assert_throws_js(TypeError, () => BluetoothUUID.getDescriptor(func));
  assert_throws_js(TypeError, () => BluetoothUUID.getDescriptor(undefined));
  assert_throws_js(TypeError, () => BluetoothUUID.getDescriptor(null));
  assert_throws_js(TypeError, () => BluetoothUUID.getDescriptor(false));
}, 'Non-number and non-strings');
