/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License,Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
//设备管理
import deviceManager from '@ohos.distributedDeviceManager';
import common from '@ohos.app.ability.common';
import Want from '@ohos.app.ability.Want';
import CommonConstants from '../constants/CommonConstants';
import { DeviceInfoInterface, AuthExtraInfoInterface } from '../constants/CommonConstants';
import Position from '../../viewmodel/Position';
import Logger from './Logger';
import { BusinessError } from '@ohos.base';


interface RejectError {
  code: number;
  message: string;
}


class DeviceData {
  device: deviceManager.DeviceBasicInfo = {
    deviceId: "",
    deviceName: "",
    deviceType: "",
    networkId: "",
  }
}


class RemoteDeviceUtil {
  private static dmInstance: RemoteDeviceUtil | undefined = undefined;
  private myDeviceManager?: deviceManager.DeviceManager;
  private localDevice?: deviceManager.DeviceBasicInfo = {
    deviceId: "",
    deviceName: "",
    deviceType: "",
    networkId: "",
  }
  private deviceList: deviceManager.DeviceBasicInfo[] = [];
  private trustDeviceList: deviceManager.DeviceBasicInfo[] = [];
  private discoverList: deviceManager.DeviceBasicInfo[] = [];
  private subscribeId: number = Math.floor(CommonConstants.SUBSCRIBE_ID_RANGE * Math.random());

  //获取实例
  static getInstance(): RemoteDeviceUtil {
    if (RemoteDeviceUtil.dmInstance === undefined) {
      RemoteDeviceUtil.dmInstance = new RemoteDeviceUtil();
    }
    return RemoteDeviceUtil.dmInstance;
  }

  //创建设备管理器
  async createDeviceManager() {
    if (this.myDeviceManager !== undefined) {
      Logger.info('remoteDeviceModel', 'createDeviceManager myDeviceManager exist');
      return;
    }
    await new Promise((resolve: (value: Object | PromiseLike<Object>) => void, reject: ((reason?: RejectError) => void)) => {
      try {
        //创建设备管理器
        this.myDeviceManager = deviceManager.createDeviceManager(CommonConstants.BUNDLE_NAME);
        //上下线监听
        this.registerDeviceStateListener();
        //获取本地设备
        this.getLocalDeviceInfo();
        //获取受信任列表
        this.getTrustedDeviceList();
        //初始化设备列表
        this.initDeviceList();

      } catch (error) {
        Logger.error('RemoteDeviceModel', `createDeviceManager failed, error=${JSON.stringify(error)}`);
      }
    })
  }

  //获取本地设备信息
  getLocalDeviceInfo(): void {
    if (this.myDeviceManager === undefined) {
      Logger.error('remoteDeviceModel', 'getLocalDeviceInfo initialized failed');
      return;
    }
    try {
      this.localDevice = {
        deviceId: "",
        deviceName: "",
        deviceType: "",
        networkId: "",
      };
      this.localDevice.deviceId = this.myDeviceManager.getLocalDeviceId();
      this.localDevice.deviceName = this.myDeviceManager.getLocalDeviceName();
      this.localDevice.deviceType = "" + this.myDeviceManager.getLocalDeviceType();
      this.localDevice.networkId = this.myDeviceManager.getLocalDeviceNetworkId();
      this.localDevice.deviceName = CommonConstants.LOCALHOST_NAME;
    } catch (error) {
      Logger.error('RemoteDeviceModel', `getLocalDeviceInfo failed, error=${JSON.stringify(error)}`);
    }
  }

  //获取受信任设备
  getTrustedDeviceList(): void {
    if (this.myDeviceManager === undefined) {
      Logger.error('RemoteDeviceModel', 'getTrustedDeviceList deviceManager has not initialized')
      return;
    }
    try {
      this.trustDeviceList = this.myDeviceManager.getAvailableDeviceListSync();
    } catch (error) {
      Logger.error('RemoteDeviceModel', `getTrustedDeviceList failed error=${JSON.stringify(error)}`);
    }
  }

  //初始化设备列表
  initDeviceList(): void {
    this.deviceList = [];
    if (this.localDevice !== undefined) {
      this.addToDeviceList(this.localDevice);
    }
    this.trustDeviceList.forEach((item: deviceManager.DeviceBasicInfo) => {
      this.addToDeviceList(item);
    })
  }

  //设备监听
  registerDeviceStateListener(): void {
    if (this.myDeviceManager === undefined) {
      Logger.error('RemoteDeviceModel', 'registerDeviceStateListener deviceManager has not initialized');
      return;
    }
    try {
      //注册设备状态改变
      this.myDeviceManager.on('deviceStateChange', (data) => {
        if (data === null) {
          return;
        }
        switch (data.action) {
        //上线
          case deviceManager.DeviceStateChange.AVAILABLE: {
            this.deviceStateChangeActionOnlice(data.device);
            break;
          }
        //下线
          case deviceManager.DeviceStateChange.UNAVAILABLE: {
            this.deviceStateChangeActionOffline(data.device);
            break;
          }
          default: {
            break;
          }
        }
      });
    } catch (error) {
      let e: BusinessError = error as BusinessError;
      Logger.error('RemoteDeviceModel', `registerDeviceStateListener on('deviceStateChange') failed, error=${e.code},${e.message}}`);
    }
  }

  //设备上线
  deviceStateChangeActionOnlice(device: deviceManager.DeviceBasicInfo): void {
    this.trustDeviceList[this.trustDeviceList.length] = device;
    this.addToDeviceList(device);
  }

  //设备下线
  deviceStateChangeActionOffline(device: deviceManager.DeviceBasicInfo): void {
    let list: deviceManager.DeviceBasicInfo[] = [];
    for (let i: number = 0; i < this.trustDeviceList.length; i++) {
      if (this.trustDeviceList[i].networkId !== device.networkId) {
        list.push(this.trustDeviceList[i])
        continue;
      }
    }
    this.deleteFromDeviceList(device);
    this.trustDeviceList = list;
  }

  //添加设备
  addToDeviceList(device: deviceManager.DeviceBasicInfo): void {
    let isExist: boolean = false;
    for (let i: number = 0; i < this.deviceList.length; i++) {
      if (device.deviceId === this.deviceList[i].deviceId) {
        this.deviceList[i] = device;
        isExist = true;
        break;
      }
    }
    if (!isExist) {
      this.deviceList.push(device);
    }
    AppStorage.setOrCreate('deviceList', this.deviceList);
  }

  //删除设备
  deleteFromDeviceList(device: deviceManager.DeviceBasicInfo): void {
    for (let i: number = 0; i < this.deviceList.length; i++) {
      if (device.deviceId === this.deviceList[i].deviceId) {
        this.deviceList.splice(i, 1);
        break;
      }
    }
    AppStorage.setOrCreate('deviceList', this.deviceList);
  }

  //注销监听
  unregisterDeviceListCallback(): void {
    if (this.myDeviceManager === undefined) {
      Logger.error('RemoteDeviceModel', 'unregisterDeviceListCallback deviceManager has not initialized');
      return;
    }

    try {
      //注销设备监听状态
      this.myDeviceManager.off('deviceStateChange');
      //释放是咧
      deviceManager.releaseDeviceManager(this.myDeviceManager);
    } catch (error) {
      Logger.error('RemoteDeviceModel', `unregisterDeviceListCallback stopDeviceDiscovery failed, error=${JSON.stringify(error)}`);
    }
  }

  //设备认证
  authenticateDevice(
    context: common.UIAbilityContext,
    device: deviceManager.DeviceBasicInfo,
    positionList: Position[]
  ): void {
    let  tempList = this.trustDeviceList.filter((item: deviceManager.DeviceBasicInfo) => device.deviceId === item.deviceId);
    if (tempList.length > 0) {
      this.startAbility(context,device,positionList);
      return;
    }

    if (this.myDeviceManager === undefined) {
      Logger.error('RemoteDeviceModel', 'authenticateDevice deviceManager has not initialized');
      return;
    }

    let extraInfo: AuthExtraInfoInterface = {
      targetPkgName: context.abilityInfo.bundleName,
      appName: context.abilityInfo.applicationInfo.name,
      appDescription: CommonConstants.APP_DESCRIPTION,
      business: CommonConstants.BUSINESS_TYPE
    };


    let bindParam: Record<string, string | number> = {
      'bindType': 1, // 认证类型: 1 - 无帐号PIN码认证
      'targetPkgName': context.abilityInfo.bundleName,
      'appName': context.abilityInfo.applicationInfo.name,
      'appOperation': 'xxxx',
      'customDescription': CommonConstants.APP_DESCRIPTION
    };

    try {
      //z执行设备认证
      this.myDeviceManager.bindTarget(device.deviceId,bindParam,(err,data) => {
        if (err) {
          Logger.error('RemoteDeviceModel', `authenticateDevice error code=${err.code}, msg=${JSON.stringify(err.message)}`);
          return;
        }
        Logger.info("bindTarget result:" + JSON.stringify(data));
      })
    }catch (error) {
      Logger.error('RemoteDeviceModel', `authenticateDevice failed error=${JSON.stringify(error)}`);
    }



  }

  //启动设备链接
  startAbility(context: common.UIAbilityContext, device: deviceManager.DeviceBasicInfo, positionList: Position[]): void {
    console.log('console');
    let wantValue: Want = {
      bundleName: context.abilityInfo.bundleName,
      abilityName: CommonConstants.ABILITY_NAME,
      deviceId: device.networkId,
      parameters: {
        positionList: JSON.stringify(positionList)
      }
    };
    //起动应用
    context.startAbility(wantValue).then(() => {
      Logger.info('RemoteDeviceModel', `startAbility finished wantValue=${JSON.stringify(wantValue)}`);
    }).catch((error: Error) => {
      Logger.error('RemoteDeviceModel', `startAbility failed, error=${JSON.stringify(error)}`);
    })
  }

  //处理新发现的设备
  deviceFound(data: DeviceData): void {
    for (let i: number = 0; i < this.deviceList.length; i++) {
      if (this.discoverList[i].deviceId === data.device.deviceId) {
        Logger.info('RemoteDeviceModel', `deviceFound device exist=${JSON.stringify(data)}`);
        return;
      }
    }
    this.deviceList[this.deviceList.length] = data.device;
    this.addToDeviceList(data.device);
  }

  //开始发现
  startDeviceDiscovery(): void {
    this.discoverList = [];
    this.initDeviceList();
    if (this.myDeviceManager === undefined) {
      Logger.error('RemoteDeviceModel', 'startDeviceDiscovery deviceManager has not initialized');
      return;
    }

    //注册发现设备
    try {
      this.myDeviceManager.on('discoverSuccess', (data: DeviceData) => {
        if (data === null) {
          return;
        }
        Logger.info('RemoteDeviceModel', `startDeviceDiscovery deviceFound data=${JSON.stringify(data)}`);
        // 处理发现的设备
        this.deviceFound(data);
      });
      this.myDeviceManager.on('discoverFailure', (data) => {
        if (data === null) {
          return;
        }
        Logger.info('RemoteDeviceModel', `startDeviceDiscovery discoverFail data=${JSON.stringify(data)}`);
      });
      let discoverParam: Record<string, number> = {
        'discoverTargetType': 1
      };
      let filterOptions: Record<string, number> = {
        'availableStatus': 0,
      };
      //开始发现
      this.myDeviceManager.startDiscovering(discoverParam);
    } catch (error) {
      Logger.error('RemoteDeviceModel', `startDeviceDiscovery failed error=${JSON.stringify(error)}`);
    }
  }

  //停止发现
  stopDeviceDiscovery(): void {
    if (this.myDeviceManager === undefined) {
      Logger.error('RemoteDeviceModel', 'stopDeviceDiscovery deviceManager has not initialized');
      return;
    }
    try {
      this.myDeviceManager.stopDiscovering();
      this.myDeviceManager.off('discoverSuccess');
    } catch (error) {
      Logger.error('RemoteDeviceModel', `stopDeviceDiscovery failed error=${JSON.stringify(error)}`);
    }
  }
}

export default RemoteDeviceUtil.getInstance();