import { PhaseItem, TaskStatus, TaskStatusList } from "@/enums/api";
import { htmlParser } from '@/utils/schema';

/**
 * 获取当前项目阶段信息
 * @param phase
 */
export const selectedPhase = (
  phaseList: { id: string; name: string; color: string }[],
  phase?: PhaseItem,

) => {
  return phaseList.filter(item => item.id === phase)
}

export function orderProperties(properties: string[], order: string[]) {
  if (!Array.isArray(order)) {
    return properties
  }

  const arrayToHash = (arr: string[]) =>
    arr.reduce((prev: any, curr: any) => {
      prev[curr] = true
      return prev
    }, {})
  const errorPropList = (arr: any) =>
    arr.length > 1 ? `properties '${arr.join("', '")}'` : `property '${arr[0]}'`

  const propertyHash = arrayToHash(properties)
  const orderFiltered = order.filter(prop => prop === '*' || propertyHash[prop])
  const orderHash = arrayToHash(orderFiltered)

  const rest = properties.filter((prop: string) => !orderHash[prop])
  const restIndex = orderFiltered.indexOf('*')
  if (restIndex === -1) {
    if (rest.length) {
      throw new Error(
        `uiSchema order list does not contain ${errorPropList(rest)}`
      )
    }
    return orderFiltered
  }
  if (restIndex !== orderFiltered.lastIndexOf('*')) {
    throw new Error('uiSchema order list contains more than one wildcard item')
  }

  const complete = [...orderFiltered]
  complete.splice(restIndex, 1, ...rest)
  return complete
}

/**
 * 获取当前任务状态信息
 * @param status
 */
export const selectedTaskStatus = (status?: TaskStatus) => {
  return TaskStatusList.filter(item => item.value === status)
}

// 获取头部区域高度(状态栏+标签栏)
export function getHeaderHeight() {
  // 微信小程序 7.0+、百度小程序、H5、App（2.0.3+）支持navigationStyle设为custom，取消默认的原生导航栏
  const info = uni.getSystemInfoSync();
  let navHeight = 0;

  // App、微信小程序、支付宝小程序、百度小程序、抖音小程序、QQ小程序、快手小程序、京东小程序
  // #ifdef MP-WEIXIN || MP-ALIPAY || MP-BAIDU || MP-TOUTIAO || MP-QQ || MP-KUAISHOU || MP-JD
  const btnInfo = uni.getMenuButtonBoundingClientRect()
  // #endif

  // 微信/百度/快手/字节跳动/京东小程序
  // #ifdef MP-WEIXIN || MP-ALIPAY || MP-BAIDU || MP-KUAISHOU || MP-TOUTIAO || MP-JD
  // console.log("btnInfo:", JSON.stringify(btnInfo), info?.statusBarHeight);
  navHeight = btnInfo?.bottom + btnInfo?.top - (info?.statusBarHeight || 0);
  // #endif

  // APP
  // #ifdef APP-PLUS
  navHeight = (info?.statusBarHeight || 0) + 45
  // #endif

  // 支付宝小程序导航栏不支持自定义，但是可以通过改变透明度，使其隐藏，且不占据文档流
  // 支付宝的titleBarHeight为标题栏高度,statusBarHeight为状态栏高度
  // #ifdef MP-ALIPAY
  navHeight = (info?.titleBarHeight || 0) + (info?.statusBarHeight || 0);
  // #endif

  // QQ在开发者工具中测试是根据top+buttom才能正确计算出高度
  // #ifdef MP-QQ 
  navHeight = btnInfo?.bottom + btnInfo?.top;
  // #endif

  // 飞书
  // // #ifdef MP-LARK
  // if(info?.navigationBarSafeArea){
  //   navHeight = (info?.navigationBarSafeArea?.height) + info?.navigationBarSafeArea?.top;
  // }
  // #endif
  return { navHeight }
}

// 获取元素的节点信息
export function getRect(selector: any, vm: any) {
  return new Promise((resolve, reject) => {
    if (!selector) reject('Parameter is empty');
    let query = null;
    // #ifdef MP-ALIPAY
    query = uni.createSelectorQuery();
    // #endif
    // #ifndef MP-ALIPAY
    query = uni.createSelectorQuery().in(vm);
    // #endif
    query.select(selector).boundingClientRect()
    query.exec(data => resolve(Array.isArray(data) ? data[0] : data));
  })
}

export const tagColor = (color: string) => {
  const colorObj: { [key: string]: { color: string, bg: string } } = {
    pinkpurple: {
      color: 'rgb(217, 26, 217)',
      bg: '#f5e8ff'
    },
    arcoblue: {
      color: 'rgb(22, 93, 255)',
      bg: '#e8f3ff'
    },
    red: {
      color: 'rgb(245, 63, 63)',
      bg: '#ffece8'
    },
    gray: {
      color: 'rgb(134, 144, 156)',
      bg: '#f2f3f5'
    },
    blue: {
      color: 'rgb(52, 145, 250)',
      bg: '#e8f7ff'
    },
    cyan: {
      color: 'rgb(20, 201, 201)',
      bg: '#e8fffb'
    },
    green: {
      color: 'rgb(0, 180, 42)',
      bg: '#e8ffea'
    },
    orange: {
      color: 'rgb(255 125 0)',
      bg: '#fff7e8'
    },
    limit: {
      color: '#9fdb1d',
      bg: '#fcffe8'
    },
    oranged: {
      color: 'rgb(247, 114, 52)',
      bg: '#fff3e8'
    },
    gold: {
      color: '#f7ba1e',
      bg: '#fffce8'
    }

  }
  return colorObj[color]
}




export function formatBytesOptimized(bytes?: number) {
  if (bytes !== undefined) {
    const BYTES_PER_UNIT = 1024
    const units = ['B', 'KB', 'MB', 'GB']
    let value = bytes
    let unitIndex = 0

    while (value >= BYTES_PER_UNIT && unitIndex < units.length - 1) {
      value /= BYTES_PER_UNIT
      // eslint-disable-next-line no-plusplus
      unitIndex++
    }

    return `${value.toFixed(2)} ${units[unitIndex]}`
  }
  return bytes
}


export function debounceFn<T extends (...args: any[]) => void>(
  callback: T,
  wait: number
): (...funcArgs: Parameters<T>) => void {
  let timeoutId: ReturnType<typeof setTimeout> | null = null;

  return function (...funcArgs: Parameters<T>): void {
    clearTimeout(timeoutId as NodeJS.Timeout);
    timeoutId = setTimeout(() => {
      callback(...funcArgs);
    }, wait);
  };
}



interface Node {
  type: 'node' | 'text';
  name?: string;
  text?: string;
  attrs?: { [key: string]: string };
  children?: Node[];
}

interface TextNode {
  type: 'text';
  text: string;
}

export function parseHTML(htmlString?: string) {
  const nodes: Node[] = [];
  let currentParent: Node | null = null;
  const stack: Node[] = [];
  if ([null, '', undefined].includes(htmlString)) {
    return []
  }
  const handler = {
    start: function(tag: string, attrs: any[], unary: boolean) {
      const element: Node = {
        type: 'node',
        name: tag,
        children: [],
        attrs: {}
      };

      attrs.forEach(attr => {
        element.attrs![attr.name] = attr.value;
      });

      if (currentParent) {
        currentParent.children!.push(element);
      } else {
        nodes.push(element);
      }

      if (!unary) {
        stack.push(element);
        currentParent = element;
      }
    },
    chars: function(text: string) {
      const textNode: Node = {
        type: 'text',
        text: text
      };

      if (currentParent) {
        currentParent.children!.push(textNode);
      } else {
        nodes.push(textNode);
      }
    },
    end: function(tag: string) {
      stack.pop();
      currentParent = stack.length > 0 ? stack[stack.length - 1] : null;
    }
  };

  htmlParser(htmlString!, handler);
  return nodes;
}





