import { arrayExpand } from 'utils/data-helper';
import { componentOperator } from './component';
import { deepMap, isComponent, isPanel, urlCacheReplace } from './utils';
import { getId } from './interaction';
import { api } from 'constants/config';
import { UserInfo } from '@/models/user.types';
import { getPanelsFromLayers } from './layer';
import { ScreensById } from '@/models/screen.types';
import { PanelsById } from '@/models/panel.types';
import flattenDeep from 'lodash/flattenDeep';

export function getScreenCenter(scale) {
  const RULER_WIDTH = 20;
  const TOOLBAR_HEIGHT = 32;

  const simulatorDom: any = document.getElementById('m-simulator');
  const containerDom: any = document.getElementById('mb-ruler');
  const { left, top, right, bottom } = simulatorDom.getBoundingClientRect();
  const {
    left: boundaryLeft,
    top: boundaryTop,
    right: boundaryRight,
    bottom: boundaryBottom,
  } = containerDom.getBoundingClientRect();

  // 超出视线范围，则按left:0,top:0位置
  if (
    left > boundaryRight ||
    right < boundaryLeft - RULER_WIDTH ||
    top > boundaryBottom - TOOLBAR_HEIGHT ||
    bottom < boundaryTop - RULER_WIDTH
  ) {
    // 数值为距离上下左右的值
    return { left: 0, top: 0 };
  }

  const realLeft = left < boundaryLeft ? boundaryLeft : left;
  const realRight = right > boundaryRight ? boundaryRight : right;
  const realTop = top < boundaryTop ? boundaryTop : top;
  const realBottom = bottom > boundaryBottom ? boundaryBottom : bottom;
  const difLeft = left - realLeft;
  const difTop = top - realTop;
  const centerX = (realRight - realLeft) / 2;
  const centerY = (realBottom - realTop) / 2;
  const simulatorX = Math.round((centerX - difLeft) / scale);
  const simulatorY = Math.round((centerY - difTop) / scale);

  return { left: simulatorX, top: simulatorY };
}

export function getConfigFromPanelConfig(panelConfig, key) {
  return panelConfig.reduce((all, item) => {
    const configs = item.stateConfig.reduce(
      (result, current) =>
        result.concat(current[key]).concat(getConfigFromPanelConfig(current.panelConfig, key)),
      [],
    );
    return all.concat(configs);
  }, []);
}

export function getTopScreenId(pathname = window.location.pathname) {
  const pathnameArr = pathname.replace(/\/+$/g,'').split('/');
  let topScreenId;
  if (/((\/create)|(\/app\/edit\/[0-9]+))\/[0-9]+\/panel_[0-9]+\/[0-9]+$/.test(pathname)) {
    topScreenId = +pathnameArr[pathnameArr.length - 3];
  } else {
    topScreenId = +pathnameArr[pathnameArr.length - 1];
  }

  return topScreenId;
}

// 通过路由或者传参，解析大屏id
export function getScreenId(pathname = window.location.pathname) {
  const pathnameArr = pathname.split('/').filter((d) => d);
  let screenId = pathnameArr[pathnameArr.length - 1];

  // 分享页面id需要base64解码
  if (/\/sharescreen\//i.test(pathname)) {
    const screenIdObj = JSON.parse(window.atob(screenId));
    screenId = screenIdObj.screenId || screenIdObj.screen_id; // screen_id是早期大屏的分享链接，这里做兼容
  }
  return +screenId;
}

// 判断是否是大屏编辑  还是终端交互编辑
export function isScreen() {
  return /\/create\/[0-9]+(\/panel_[0-9]+\/[0-9]+)?$/.test(window.location.pathname);
}

export function isMobileScreen() {
  return /\/app\/edit\/[0-9]+?\/[0-9]+?$/.test(window.location.pathname);
}

export function getScreenComponents(
  id,
  { componentsById = {}, screensById = {}, panelsById = {} },
) {
  const screen = screensById[id];
  if (!screen) {
    return [];
  }

  const { layers = [] } = screen;

  const components: any = [];

  deepMap(layers, (item: any) => {
    if (isComponent(item.id)) {
      const component = componentsById[item.id];
      if (component) {
        components.push(component);
      }
    } else if (isPanel(item.id)) {
      const panel = panelsById[getId(item.id) as number];
      if (panel) {
        const { states = [] } = panel;
        states.map((d) => {
          components.push(...getScreenComponents(d, { componentsById, screensById, panelsById }));
        });
      }
    }
  });

  return components;
}

export function joinFilter(filter: any): string | undefined {
  if (!filter || typeof filter !== 'object') {
    return;
  }

  const { open, hue, brightness, contrast, grayscale, opacity, saturate } = filter;
  if (open) {
    let result = '';
    result = hue ? `${result} hue-rotate(${hue}deg)` : result;
    result = brightness ? `${result} brightness(${brightness + 100}%)` : result;
    result = contrast ? `${result} contrast(${contrast + 100}%)` : result;
    result = grayscale ? `${result} grayscale(${grayscale}%)` : result;
    result = opacity != null && opacity !== 100 ? `${result} opacity(${opacity}%)` : result;
    result = saturate ? `${result} saturate(${saturate + 100}%)` : result;
    return result;
  } else {
    return 'unset';
  }
}

export const screenOperator = {
  create({
    id,
    name,
    config,
    layers,
    thumb,
    panelId,
    mobileId,
    groupId,
    lines,
    leftBarWidth,
    share,
    sharePassword,
    dataAlert,
    showLoading,
    tenantId,
  }) {
    return {
      id,
      name,
      // 右侧面板信息
      config: config || {},
      // 左侧层级信息 id,name,show,lock,collapsed, 本地临时变量focus
      layers: layers || [],
      // 可以从layers里拿
      // components: components || [],
      thumb,
      groupId,
      lines: lines,
      leftBarWidth: leftBarWidth || 200,
      // 'null' is top level
      panelId: panelId || null,
      mobileId,
      share,
      sharePassword,
      dataAlert,
      showLoading,
      tenantId,
    };
  },
  createFromServer({
    id,
    name,
    config = [],
    layers = [],
    filters = [],
    lines = { h: [], v: [] },
    leftBarWidth = 200,
    thumb,
    panelId,
    mobileId,
    share,
    shareToken,
    shareInfo,
    sharePassword,
    globalFilter = {},
    isShowAlert,
    isShowLoading,
    apps = [],
    tenantId,
  }) {
    globalFilter = globalFilter || {};

    return {
      id: id,
      name: name,
      config: config,
      layers: layers,
      filters: filters,
      lines: lines,
      leftBarWidth: leftBarWidth || 200,
      thumb: thumb,
      share: share,
      shareToken: shareToken,
      shareInfo: shareInfo,
      sharePassword: sharePassword,
      panelId: panelId,
      mobileId: mobileId,
      globalFilter: globalFilter,
      dataAlert: isShowAlert,
      showLoading: isShowLoading,
      apps,
      tenantId,
    };
  },
  // 从layers对象列表 解析返回componentid和panelid
  getComponentsFromLayers(layers) {
    if (!Array.isArray(layers)) layers = [layers];
    const found: any = [];
    arrayExpand(
      layers,
      (item) => item.components,
      (item) => {
        if (!componentOperator.isGroup(item.id)) found.push(item.id);
      },
    );
    return found;
  },
  // 根据选中图层id列表和图层对象列表 解析返回componentid和panelid
  getComponentsFromSelectedLayers: (selected: any = [], layers: any = []) => {
    if (!Array.isArray(selected)) selected = [selected];

    const found: any = [];
    arrayExpand(
      layers,
      (item) => item.components,
      (item) => {
        if (~selected.indexOf(item.id)) {
          if (componentOperator.isGroup(item.id)) {
            found.push(...screenOperator.getComponentsFromLayers(item.components));
            return false;
          } else {
            found.push(item.id);
          }
        }
      },
    );
    return found;
  },
  // 查找图层
  findLayerById(id, layers): any {
    let found = {};
    arrayExpand(
      layers,
      (item) => item.components,
      (item) => {
        if (item.id === id) {
          found = item;
          return 'stop';
        }
      },
    );
    return found;
  },
  // 计算focus图层 返回set
  computeFocusLayers(
    layers: any[] = [],
    focusLayers: (number | string)[] = [],
  ): Set<number | string> | null {
    let hasFocus = false;
    const focusSet: Set<number | string> = new Set();
    // 递归当前屏幕layers 找到设置了灯泡的图层 将其加入集合
    // 如果是group设置了灯泡的情况 将其子图层全部加入集合
    arrayExpand(
      layers,
      (item) => item.components,
      (item: { id: string | number; components: any[] }) => {
        if (~focusLayers.indexOf(item.id)) {
          hasFocus = true;
          focusSet.add(item.id);
          if (componentOperator.isGroup(item.id)) {
            screenOperator
              .getComponentsFromLayers(item.components)
              .forEach((id) => focusSet.add(id));
            return false;
          }
        }
      },
    );
    return hasFocus ? focusSet : null;
  },
};
/**
 * 根据路由返回对应的请求引用面板的接口
 */
export const getPanelApi = () => {
  const pathname = window.location.pathname;
  if (/\/sharedPortal\//i.test(pathname)) return api.sharedGatewayPanelGet; //v3 门户管理获取panel
  if (/\/sharescreen\//i.test(pathname)) return urlCacheReplace(api.sharedPanelGet); //v5 发布页获取panel
  if (/\/insert\/screen\//i.test(pathname)) return api.appPanelGet; //v3
  if (/\/app\/detail\//i.test(pathname)) return api.panelGetOfChecked; //v5 终端远程访问获取引用面板
  return api.panelGet; //v5 大屏编辑页获取panel
};

/**
 * @description 根据当前页面路由返回获取大屏的API接口
 * @param userInfo checkMode时必须
 * @returns
 */
export const getScreenDataApiByPathName = (userInfo: UserInfo) => {
  const pathname = window.location.pathname;
  if (/\/sharedPortal\//.test(pathname)) return api.sharedGatewayScreenGet;
  if (/\/sharescreen\//i.test(pathname)) {
    return urlCacheReplace(api.screenSharedGet);
  }
  if (/\/insert\/screen\//i.test(pathname)) return api.screenInsertGet;
  if (
    /checkMode=login/.test(window.location.href) ||
    userInfo?.userId ||
    /\/spaceShipEdit\//i.test(pathname) ||
    /\/spaceShipPreview\//i.test(pathname)
  )
    return api.screenGet;
  return api.screenGetByCode;
};

/**
 *
 * @param screenId
 * @param screensById
 * @param panelsById
 * @returns 根据主屏ID获取一级（引用面板、动态面板、分组里的引用面板和动态面板的主屏）子屏ID
 */
export const getFirstLevelSubScreenIds = (
  screenId: number,
  screensById: ScreensById,
  panelsById: PanelsById,
) => {
  const curLayers = screensById[screenId]?.layers || [];
  const panelIds = getPanelsFromLayers(curLayers).map((d) => getId(d.id));
  return [
    ...new Set(
      panelIds.reduce((pre, cur) => {
        if (panelsById[cur]?.states) {
          return pre.concat(panelsById[cur].states);
        }
        return pre;
      }, []),
    ),
  ].map((d) => Number(d));
};

/**
 *
 * @param mainId
 * @param screensById
 * @param panelsById
 * @param filterIds
 * @returns 根据主屏ID获取所有子屏ID集合，没有被扁平化
 */
export const getAllSubScreenIds = (
  mainId: number,
  screensById: ScreensById,
  panelsById: PanelsById,
  filterIds: number[],
) => {
  const curScreensId = getFirstLevelSubScreenIds(mainId, screensById, panelsById).filter((d) =>
    filterIds.includes(d),
  );
  return curScreensId.map((d) => {
    return [
      d,
      getAllSubScreenIds(
        d,
        screensById,
        panelsById,
        filterIds.filter((d) => !curScreensId.includes(d)),
      ),
    ];
  });
};

/**
 *
 * @param mainId
 * @param screensById
 * @param panelsById
 * @param filterIds
 * @returns 根据主屏获取扁平化之后的所有子屏ID集合
 */
export const getAllFlattenedSubScreenIds = (
  mainId: number,
  screensById: ScreensById,
  panelsById: PanelsById,
  filterIds: number[],
) => {
  return flattenDeep(getAllSubScreenIds(mainId, screensById, panelsById, filterIds)) as number[];
};
