import type { StaticImg } from '@/utils/static'
import { onLoad } from '@dcloudio/uni-app'
import { reactive, toRefs, nextTick} from 'vue'
import { inject, onUnmounted, onMounted, type ComponentInternalInstance, ref} from 'vue'
import { encode, decode} from 'js-base64'
import hand from '@/assets/3-4.png'

/**
 * 它从 `inject` 函数返回 `StaticImg` 服务
 * 图片的key就是图片名称
 * @returns { StaticImg } assets下全部的文件
 * @example
 * const staticImg = useStaticImg()
 * const logo = staticImg.logo
 */
export const useStaticImg = (): StaticImg => inject<StaticImg>("staticImg")!

/**
 *
 * @description 重复执行的定时器， 会在组件的unMounted阶段销毁
 *
 */
export const useScheduler = (cb: () => void, delay: number) => {

  const stx: API.UseSchedulerFastCall = {
    timeId: null,
    start: () => {},
    pause: () => {},
    stop: () => {},
    onPlaying: () => {}
  }

  let timeId = ref<number>()

  const playing = () => {}

  const clearScheduler = () => {
    console.log('暂停计时器:', timeId.value);
    
    clearInterval(timeId.value as number)
  }

  onUnmounted(clearScheduler)

  stx.start = () => {
    timeId.value = setInterval(() => {
      cb()
      playing()
    }, delay)
  }

  stx.pause = () => clearScheduler()

  stx.onPlaying = playing

  stx.stop = () => clearScheduler()

  return stx
}

/**
 * @description 执行一定的定时器， 会在执行完后销毁
 * @param cb  回调函数
 * @param delay 延迟 大部分浏览器setTimeout延迟默认在四毫秒左右
 */
export const useSchedulerOnce = (
  cb: () => void,
  delay: number = 4
): void => {
  const timeId = setTimeout(() => {
    cb()
    clearTimeout(timeId)
  }, delay)
  onUnmounted(() => clearTimeout(timeId))
}

/**
 * 它返回一个对象，其中包含导航栏的高度、导航栏内内容的高度以及导航栏的顶部位置。
 * @returns 具有 height、contentHeight 和 top 属性的对象。
 */
export const useNavbarInfo = () => {

  const { uniPlatform, safeArea , ...systemInfo} = uni.getSystemInfoSync()

  console.log(uniPlatform,  window['navigatorBarHeight'], window['statusBarHeight']);
  
  if (uniPlatform == "web") {
    const statusBarHeight = window['statusBarHeight'] ? window['statusBarHeight'] * 2 : 33
    return {
      height: 140 + statusBarHeight  + "rpx",
      contentHeight: '64rpx',
      top: 38 + statusBarHeight + 'rpx',
      left: '40rpx',
      safeAreaTop: statusBarHeight + 'rpx',
      statusBarHeight: statusBarHeight
    }
  
  } else {

    const bounding = uni.getMenuButtonBoundingClientRect()
    console.log("(safeArea!.top + bounding.height):", (safeArea!.top + bounding.height));
    
    return {
      height: 104 + 'px',
      contentHeight: bounding.height + (bounding.top - systemInfo.statusBarHeight!) * 2 + "px",
      top: systemInfo.statusBarHeight!  + "px",
      left: '20px',
      safeAreaTop: 0 + 'rpx',
      statusBarHeight: 0
    }
  }

}

/**
 * 它需要一个 id、一个回调函数和一个 vm，然后它使用具有给定 id 的元素的 boundingClientRect 调用回调函数
 * @param {string} id - 您要从中获取信息的元素的 ID
 * @param cb - 回调函数
 * @param {ComponentInternalInstance} vm - 组件实例
 */
export const useQueryElInfo = (
  id: string,
  cb: (params: UniApp.NodeInfo | UniApp.NodeInfo[] ) => void,
  vm?: ComponentInternalInstance,
  immediate: boolean = true
) => {

  const queryNode = () => {
    const query = vm ? uni.createSelectorQuery().in(vm) :  uni.createSelectorQuery();
    query.select(id).boundingClientRect(data => cb(data)).exec();
  }

  // onMounted(() => queryNode())

  immediate ? onMounted(() => queryNode()) : queryNode()
}

/**
 * 它创建一个音频实例，并返回一个具有 destroy、play 和 onPlayend 方法的对象。
 * @param {string} src - 音频文件的来源
 * @returns 具有三个属性的对象：destroy、play 和 onPlayend。
 */
export const useAudioMange = (src?: string) => {

  const audioInstance = ref< UniApp.InnerAudioContext>()
 
  audioInstance.value = uni.createInnerAudioContext()

  if (src) {
    console.log('src');
    
    audioInstance.value.src = src
  }

  const destroy = () => audioInstance.value?.stop()

  const play = (src: string) => {
    audioInstance.value!.src = src
    console.log(src, audioInstance.value);
    
    useSchedulerOnce(() => {
      console.log('play');
      audioInstance.value?.play()
    }, 500)

  }

  audioInstance.value.autoplay = true

  audioInstance.value!.onCanplay((e) => {
    console.log('onCanplay:111', e);
  })

  audioInstance.value?.onError((e) => {
    console.log(e);
  })

  const onplayend = (cb: Function) => audioInstance.value?.onEnded(() => cb && cb())

  onUnmounted(() => {
    destroy()
  })

  const atx = {
    destroy,
    play,
    onplayend,
  }

  return atx

}

/**
 * 它以字符串形式返回设备平台。
 * @returns uniPlatform 作为 DEVICE.Platform 返回。
 */
export const usePlatform = (): DEVICE.Platform => {

  const { uniPlatform } = uni.getSystemInfoSync()

  return uniPlatform as DEVICE.Platform

}

/**
 * 获取多设备动态适配的比率
 * @example
 *  const rate = useAdaptationIpadAndPhone()
 *  node.width = node.width * rate * 2 + 'rpx
 */
export const useAdaptationIpadAndPhone = () => {
  let a = window.innerWidth / window.innerHeight > 0.5 ? 667 / ( window.innerHeight ) : 1

  const resizeHanlde = () => {
    // 获取当前窗口的宽度
    var screenWidth = window.innerWidth;
    var screenHeight = window.innerHeight;

    const rate = screenWidth / screenHeight

    if ( rate > 0.5 ) { // 大于0.6 说明是平板 
      a = 667 / (  screenHeight )
    } else {
      a = 1
    }
  }

  // 监听窗口尺寸变化事件
  window.addEventListener('resize', resizeHanlde);

  return a
}

export const useQueryParmas = async () => {
  let state = reactive({})
  
  state = await new Promise( (resolve) => {
    onLoad(query => {
      console.log(3);
      resolve(query!)
    })
  })
  
  return {...toRefs(state)}
}

/**
 * 这是一个导出对象的TypeScript函数，有两个方法decode和encode，分别将Base64编码的字符串解码为JSON对象，将JSON对象编码为Base64编码的字符串。
 * @returns 正在返回名为“useBase64”的自定义挂钩。这个钩子有两个函数：`decode` 和 `encode`。 `decode` 函数将字符串作为输入并返回解析后的 JSON 对象。
 * `encode` 函数将 `API.P` 类型的对象作为输入并返回 base64 编码的字符串。
 */
export const useBase64 = () => {

  return {
    decode: <T>(URI: string): T => JSON.parse(decode(URI)),
    encode: (records: API.P): string => encode(JSON.stringify(records))
  }

}


/**
 * @description 获取设备方向
 * @param cb
 */
export const useDeviceDire = (cb: (dire: 'H' | 'V') => void) => {
  const getDire = () => {
    if (window.orientation === 180 || window.orientation === 0) {
      cb('V')
    }
    if (window.orientation === 90 || window.orientation === -90) {
      cb('H')
    }
  }

  window.addEventListener('orientationchange', getDire)

  onMounted(getDire)

  onUnmounted(() => {
    window.removeEventListener('orientationchange', () => {})
  })
}


/**
 * @description 题卡的放大镜功能
 */
export const useMagnifier = async (
  canvas: HTMLCanvasElement, 
  canvasId: string, 
  { ansUrl,  quesUrl, instance, rate } 
  : 
  { ansUrl: string,  quesUrl: string, instance: ComponentInternalInstance, rate: number}
) => {

  const adaptatio = useAdaptationIpadAndPhone()

  let ctx: UniApp.CanvasContext = uni.createCanvasContext(canvasId)

  const deviceWidthRate = uni.getSystemInfoSync().windowWidth / 375

  // 初始化放大镜的参数
  const magnifierSize = 150 * deviceWidthRate  ; // 放大镜尺寸
  const magnification = 1.5 ; // 放大倍数
  const lineWidth = 6 * deviceWidthRate// 放大镜边框宽度

  let _moveMagnifier = (event: TouchEvent) => {}

  const createImgStr = async () => {
    ctx.drawImage(quesUrl, 0, 0, 224 * deviceWidthRate, 386 * deviceWidthRate)
    // ctx.save()
    ctx.drawImage(ansUrl, 225 * deviceWidthRate , 0, 75  * deviceWidthRate, 386 * deviceWidthRate)
    ctx.save()
    ctx.draw()
    ctx.restore();
    // 创建 Image 对象并加载图片
    await new Promise( resolve => {
        useSchedulerOnce(() => {
          resolve(true)
        }, 100)
    })
  
    return await new Promise((resolve) => {
        uni.canvasToTempFilePath({
          canvasId: canvasId,
          fileType: 'png',
          quality: 1,
          destWidth: 300 * deviceWidthRate,
          destHeight: 386 * deviceWidthRate,
          success: (res) => resolve( res.tempFilePath),
          fail: (error) => {
            console.error('canvasToTempFilePath failed: ', error);
          }
        }, instance);
    }) as string
  }

  const draw = async () => {

    const imgStr = await createImgStr()
    
    function initMagnifier () {
          // 计算放大镜区域的位置和尺寸
          const startX = 0;
          const startY = 0;
          const width = magnifierSize;
          const height = magnifierSize;

          // 绘制阴影
          ctx.shadowColor = 'black';
          ctx.shadowBlur = 20;
          ctx.shadowOffsetX = 0;
          ctx.shadowOffsetY = 0;
          

          // 绘制放大镜效果
          ctx.save();
          ctx.beginPath();
          ctx.arc(
            magnifierSize / 2,
            magnifierSize / 2,
            magnifierSize / 2,
            0,
            2 * Math.PI
          );
          ctx.strokeStyle = 'yellow'; // 设置边框颜色为黄色
          ctx.lineWidth = lineWidth; // 设置边框宽度
          ctx.stroke(); // 绘制边框
          ctx.closePath();
          ctx.clip();
          ctx.drawImage(
            imgStr,
            startX,
            startY,
            width,
            height,
            0 - magnifierSize / 2,
            0 - magnifierSize / 2,
            magnifierSize * magnification,
            magnifierSize * magnification
          );
          ctx.draw()
          ctx.restore();
    }
    
    function moveMagnifier (event: TouchEvent) {
          
          event.preventDefault();
          event.stopPropagation();
          const mouseX = (event.touches[0].pageX - canvas.getBoundingClientRect().left) / adaptatio 
          const mouseY = (event.touches[0].pageY -  canvas.getBoundingClientRect().top) / adaptatio
  
          // 清空 Canvas
          ctx.clearRect(0, 0, canvas.clientWidth, canvas.clientHeight);
      
          // 计算放大镜区域的位置和尺寸
          const startX = (mouseX - magnifierSize / 2)
          const startY = (mouseY - magnifierSize / 2)
          const width = magnifierSize;
          const height = magnifierSize;
      
          // 绘制放大镜效果
          ctx.save();
          ctx.beginPath();
          ctx.arc(mouseX, mouseY, magnifierSize / 2, 0, 2 * Math.PI);
          ctx.strokeStyle = 'yellow';
          ctx.lineWidth = lineWidth; 
          ctx.stroke()
          ctx.closePath();
          ctx.clip();
          ctx.drawImage(
            imgStr,
            startX,
            startY,
            width,
            height,
            mouseX - (magnifierSize * magnification) / 2,
            mouseY - (magnifierSize * magnification) / 2,
            magnifierSize * magnification,
            magnifierSize * magnification
          );
          ctx.draw()
          ctx.restore();
    }

    _moveMagnifier = moveMagnifier

    initMagnifier();

    // 监听鼠标移动事件，实现放大镜效果
    canvas.addEventListener("touchmove",moveMagnifier);
  }

  const clear = () => {
    ctx.clearRect(0, 0, canvas.clientWidth, canvas.clientHeight);
    ctx.draw()
    canvas.removeEventListener('touchmove', _moveMagnifier)
  }

  onUnmounted(() => {
    canvas.removeEventListener('touchmove', _moveMagnifier)
  })
  
  return {
    draw, clear
  }
};



/**
 * 陀螺仪
 */
export const useGyro = async () => {
  const handleOrientation = (event: DeviceOrientationEvent) => {

    var alpha = event.alpha; // 设备绕 Z 轴的旋转角度（0 到 360 度）
    var beta = event.beta!;   // 设备绕 X 轴的旋转角度（-180 到 180 度）
    var gamma = event.gamma; // 设备绕 Y 轴的旋转角度（-90 到 90 度）

    console.log('beta', beta);
    
    if ( beta > 45 && beta <= 270 ) {
      console.log('顺时针横屏');
    } else if ( beta < -45 && beta >= -270 ) {
      console.log('逆時針横屏');
    }

  }
  if (window.DeviceOrientationEvent) {
    console.log('设备支持陀螺仪功能');
    // 支持陀螺仪功能
    window.addEventListener('deviceorientation', handleOrientation);
  } else {
    console.log('设备不支持陀螺仪功能');
  }

  onUnmounted(() => {
    window.removeEventListener('deviceorientation', handleOrientation)
  })
}
