'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

var bluetoothBump_utils = require('./utils.js');
require('@babel/runtime/helpers/slicedToArray');
require('@babel/runtime/helpers/typeof');
require('./constants.js');

/**
 * 微信蓝牙 API 薄封装
 *
 * 把所有对 wx.* 的直接调用集中在这一层，外部只看到 Promise / 回调注册接口。
 * 这样：
 *   1. 主流程类 BluetoothBump 不直接依赖 wx，可注入 mock adapter 做单测
 *   2. 这里的实现也能单独被测：mock 一个 (global as any).wx 就够了
 */
// -------------------- 内部小工具 --------------------
function openAdapterWithMode(mode) {
  return new Promise(function (resolve, reject) {
    var params = {
      success: function success() {
        return resolve();
      },
      fail: function fail(err) {
        return reject(err);
      }
    };
    if (mode) params.mode = mode;
    wx.openBluetoothAdapter(params);
  });
}
// -------------------- 默认实现 --------------------
var wxBluetoothAdapter = {
  isAvailable: function isAvailable() {
    return typeof wx !== 'undefined' && !!wx && typeof wx.openBluetoothAdapter === 'function';
  },
  detectPlatform: function detectPlatform() {
    if (typeof wx === 'undefined' || !wx.getSystemInfoSync) return 'unknown';
    try {
      var info = wx.getSystemInfoSync();
      return (info.platform || 'unknown').toLowerCase();
    } catch (e) {
      return 'unknown';
    }
  },
  ensurePrivacyAuthorized: function ensurePrivacyAuthorized(privacyContent, log) {
    return new Promise(function (resolve) {
      if (typeof wx === 'undefined' || !wx) {
        resolve();
        return;
      }
      if (typeof wx.onNeedPrivacyAuthorization !== 'function') {
        resolve();
        return;
      }
      var resolved = false;
      var safeResolve = function safeResolve() {
        if (resolved) return;
        resolved = true;
        resolve();
      };
      wx.onNeedPrivacyAuthorization(function (resolveAuth) {
        log('微信请求隐私授权，弹出协议确认');
        wx.showModal({
          title: '隐私保护指引',
          content: privacyContent,
          confirmText: '同意',
          cancelText: '拒绝',
          success: function success(modalRes) {
            if (modalRes.confirm) {
              log('✅ 用户同意隐私协议');
              resolveAuth({
                event: 'agree',
                buttonId: 'agree-btn'
              });
            } else {
              log('⚠️ 用户拒绝隐私协议');
              resolveAuth({
                event: 'disagree'
              });
            }
          },
          fail: function fail() {
            return resolveAuth({
              event: 'disagree'
            });
          }
        });
      });
      if (typeof wx.requirePrivacyAuthorize === 'function') {
        wx.requirePrivacyAuthorize({
          success: function success() {
            return safeResolve();
          },
          fail: function fail() {
            return safeResolve();
          }
        });
      } else {
        safeResolve();
      }
    });
  },
  openAdapter: function openAdapter(platform, log) {
    if (platform === 'ios') {
      return openAdapterWithMode('central').then(function () {
        log('✅ Central 模式适配器已打开');
        return openAdapterWithMode('peripheral').then(function () {
          log('✅ Peripheral 模式适配器已打开');
          return {
            skipAdvertising: false
          };
        })["catch"](function (err) {
          log("\u26A0\uFE0F Peripheral \u6A21\u5F0F\u521D\u59CB\u5316\u5931\u8D25\uFF0C\u964D\u7EA7\u4E3A\u53EA\u626B\u63CF\uFF1A".concat((err === null || err === void 0 ? void 0 : err.errMsg) ? err.errMsg : err));
          return {
            skipAdvertising: true
          };
        });
      });
    }
    return openAdapterWithMode().then(function () {
      return {
        skipAdvertising: false
      };
    });
  },
  startAdvertising: function startAdvertising(params) {
    return new Promise(function (resolve, reject) {
      wx.createBLEPeripheralServer({
        success: function success(res) {
          var server = res === null || res === void 0 ? void 0 : res.server;
          if (!server || typeof server.addService !== 'function') {
            reject(new Error('createBLEPeripheralServer 返回的 server 无效（不支持外围模式）'));
            return;
          }
          var valueStr = params.payload || params.tempId;
          var valueBuf = bluetoothBump_utils.str2ArrayBuffer(valueStr);
          // 从 payload 里拆出 myTempId / seenPeerId，用来生成设备名
          // 设备名是 iOS↔iOS 唯一可靠的广播通道（CoreBluetooth 不允许发 ServiceData）
          var parsed = bluetoothBump_utils.parsePayloadString(valueStr);
          var myTempId = (parsed === null || parsed === void 0 ? void 0 : parsed.myTempId) || params.tempId;
          var seenPeerId = (parsed === null || parsed === void 0 ? void 0 : parsed.seenPeerId) || '';
          var bumpName = bluetoothBump_utils.encodeBumpName(myTempId, seenPeerId);
          server.addService({
            service: {
              uuid: params.serviceUuid,
              characteristics: [{
                uuid: params.characteristicUuid,
                properties: {
                  read: true,
                  write: true,
                  notify: false,
                  indicate: false
                },
                permission: {
                  readable: true,
                  writeable: true
                },
                value: valueBuf
              }]
            },
            success: function success() {
              // ⚠️ 关键：iOS 不能在广播包里发 ServiceData，但能发 deviceName + serviceUuids。
              //    所以把 payload 同时写进：
              //      a) deviceName: BUMP_<myTempId>_<seenPeerId>——iOS↔iOS 唯一可靠通道
              //      b) serviceData（数组/对象两种格式）——Android 能读到更多位
              //    三重带 fallback，谁能走通谁走
              var _tryAdvertise = function tryAdvertise(advertiseRequest, fallbacks) {
                server.startAdvertising({
                  advertiseRequest: advertiseRequest,
                  success: function success() {
                    return resolve({
                      server: server
                    });
                  },
                  fail: function fail(err) {
                    if (fallbacks.length) {
                      var next = fallbacks.shift();
                      _tryAdvertise(next, fallbacks);
                    } else {
                      reject(err);
                    }
                  }
                });
              };
              var serviceDataObj = {};
              serviceDataObj[params.serviceUuid] = valueBuf;
              _tryAdvertise({
                // 首选：名字 + serviceUuids + serviceData(数组)
                deviceName: bumpName,
                serviceUuids: [params.serviceUuid],
                serviceData: [{
                  uuid: params.serviceUuid,
                  data: valueBuf
                }]
              }, [
              // 备选 1：名字 + serviceUuids + serviceData(对象格式)
              {
                deviceName: bumpName,
                serviceUuids: [params.serviceUuid],
                serviceData: serviceDataObj
              },
              // 备选 2：仅名字 + serviceUuids（iOS 上实际走这里，payload 靠名字传）
              {
                deviceName: bumpName,
                serviceUuids: [params.serviceUuid]
              },
              // 备选 3：裸跑（极端降级，对端可能拿不到 payload）
              {
                serviceUuids: [params.serviceUuid]
              }]);
            },
            fail: function fail(err) {
              return reject(err);
            }
          });
        },
        fail: function fail(err) {
          return reject(err);
        }
      });
    });
  },
  updateAdvertisedValue: function updateAdvertisedValue(server, params) {
    return new Promise(function (resolve, reject) {
      if (!server || typeof server.addService !== 'function') {
        reject(new Error('server 无效，无法更新广播 value'));
        return;
      }
      var valueStr = params.payload || params.tempId;
      var valueBuf = bluetoothBump_utils.str2ArrayBuffer(valueStr);
      var parsed = bluetoothBump_utils.parsePayloadString(valueStr);
      var myTempId = (parsed === null || parsed === void 0 ? void 0 : parsed.myTempId) || params.tempId;
      var seenPeerId = (parsed === null || parsed === void 0 ? void 0 : parsed.seenPeerId) || '';
      var bumpName = bluetoothBump_utils.encodeBumpName(myTempId, seenPeerId);
      var doAddAndStart = function doAddAndStart() {
        server.addService({
          service: {
            uuid: params.serviceUuid,
            characteristics: [{
              uuid: params.characteristicUuid,
              properties: {
                read: true,
                write: true,
                notify: false,
                indicate: false
              },
              permission: {
                readable: true,
                writeable: true
              },
              value: valueBuf
            }]
          },
          success: function success() {
            // 同 startAdvertising：名字 + serviceData 三重 fallback
            var _tryAdvertise2 = function tryAdvertise(advertiseRequest, fallbacks) {
              server.startAdvertising({
                advertiseRequest: advertiseRequest,
                success: function success() {
                  return resolve();
                },
                fail: function fail(err) {
                  if (fallbacks.length) {
                    var next = fallbacks.shift();
                    _tryAdvertise2(next, fallbacks);
                  } else {
                    reject(err);
                  }
                }
              });
            };
            var serviceDataObj = {};
            serviceDataObj[params.serviceUuid] = valueBuf;
            _tryAdvertise2({
              deviceName: bumpName,
              serviceUuids: [params.serviceUuid],
              serviceData: [{
                uuid: params.serviceUuid,
                data: valueBuf
              }]
            }, [{
              deviceName: bumpName,
              serviceUuids: [params.serviceUuid],
              serviceData: serviceDataObj
            }, {
              deviceName: bumpName,
              serviceUuids: [params.serviceUuid]
            }, {
              serviceUuids: [params.serviceUuid]
            }]);
          },
          fail: function fail(err) {
            return reject(err);
          }
        });
      };
      var afterStop = function afterStop() {
        if (typeof server.removeService === 'function') {
          server.removeService({
            serviceId: params.serviceUuid,
            success: function success() {
              return doAddAndStart();
            },
            fail: function fail() {
              return doAddAndStart();
            } // removeService 失败也继续，addService 重复注册会报错再在上层回退
          });
        } else {
          doAddAndStart();
        }
      };
      if (typeof server.stopAdvertising === 'function') {
        server.stopAdvertising({
          success: function success() {
            return afterStop();
          },
          fail: function fail() {
            return afterStop();
          } // 忽略停止失败，继续尝试更新
        });
      } else {
        afterStop();
      }
    });
  },
  startDiscovery: function startDiscovery(params) {
    return new Promise(function (resolve, reject) {
      var wxParams = {
        allowDuplicatesKey: true,
        interval: 0,
        success: function success() {
          return resolve();
        },
        fail: function fail(err) {
          return reject(err);
        }
      };
      // ⚠️ iOS 不传 services 过滤，否则系统重新包装广播包后会扫不到
      if (params.platform !== 'ios') {
        wxParams.services = [params.serviceUuid];
      }
      wx.startBluetoothDevicesDiscovery(wxParams);
    });
  },
  onDeviceFound: function onDeviceFound(cb) {
    wx.onBluetoothDeviceFound(cb);
  },
  offDeviceFound: function offDeviceFound(cb) {
    if (wx && typeof wx.offBluetoothDeviceFound === 'function') {
      wx.offBluetoothDeviceFound(cb);
    }
  },
  onAdapterStateChange: function onAdapterStateChange(cb) {
    wx.onBluetoothAdapterStateChange(cb);
  },
  offAdapterStateChange: function offAdapterStateChange(cb) {
    if (wx && typeof wx.offBluetoothAdapterStateChange === 'function') {
      wx.offBluetoothAdapterStateChange(cb);
    }
  },
  getDevices: function getDevices() {
    return new Promise(function (resolve) {
      if (!wx || typeof wx.getBluetoothDevices !== 'function') {
        resolve({
          devices: []
        });
        return;
      }
      wx.getBluetoothDevices({
        success: function success(res) {
          return resolve({
            devices: (res === null || res === void 0 ? void 0 : res.devices) || []
          });
        },
        fail: function fail() {
          return resolve({
            devices: []
          });
        }
      });
    });
  },
  stopDiscovery: function stopDiscovery() {
    if (wx && typeof wx.stopBluetoothDevicesDiscovery === 'function') {
      wx.stopBluetoothDevicesDiscovery({});
    }
  },
  stopAdvertising: function stopAdvertising(server) {
    if (server && typeof server.stopAdvertising === 'function') {
      server.stopAdvertising({});
    }
  },
  closeAdapter: function closeAdapter() {
    if (wx && typeof wx.closeBluetoothAdapter === 'function') {
      wx.closeBluetoothAdapter({});
    }
  }
};

exports.wxBluetoothAdapter = wxBluetoothAdapter;
