import http, { request } from 'utils/fetch';
import { api } from 'constants/config';
import { actionTypes } from 'constants/action-types';
import { getPanelInfoForScreenEdit } from 'models/panel';
import { toObject, isOrder, getFirstSelectedId, getPanelsFromLayers } from 'utils/layer';
import { getScreenCenter, getTopScreenId } from 'utils/screen';
import { componentOperator, getComponentDimension, getGroupChildren, transformComponents } from 'utils/component';
import { uploadAssets } from 'utils/upload';
import { getId } from 'utils/interaction';
import { favoriteCreate } from 'models/material-lib';
import { isGeneralPanel, isComponent, isGroup } from 'utils/utils';
import message from 'components/message';
import { commponentsAdd } from './component';

export function getFavorites() {
  return async (dispatch) => {
    dispatch({
      type: actionTypes.FAVORITE_GET_LIST_START
    });

    const result = await http.get(api.favoriteList);

    if (result) {
      dispatch({
        type: actionTypes.FAVORITE_GET_LIST_SUCCESS,
        payload: result
      });
    } else {
      dispatch({
        type: actionTypes.FAVORITE_GET_LIST_FAILURE
      });
    }
  };
}

export function createFavorite({ name, thumb, userCategoryId }) {
  return async (dispatch, getState) => {
    const { createApp, componentsById, screensById, panelsById } = getState();
    const { id, layersSelected } = createApp;
    const { layers } = screensById[id];
    const layersById = toObject(layers);

    dispatch({
      type: actionTypes.FAVORITE_CREATE_START
    });
    let thumbPath = thumb;
    if (typeof thumb === 'object' && thumb !== null) {
      const result = await uploadAssets({
        path: `thumb/${thumb.name}`,
        file: thumb
      });
      if (!result) {
        dispatch({
          type: actionTypes.FAVORITE_CREATE_FAILURE
        });
        return;
      }
      thumbPath = result;
    }
    const favoriteLayers = layersSelected.map((d) => layersById[d]);
    favoriteLayers.sort((a, b) => (isOrder(a.path, b.path) ? -1 : 1));

    const componentsId: any = [];
    const panelsId: any = [];
    const sperateIds = (ids) => {
      ids.forEach((d) => {
        if (isComponent(d)) {
          componentsId.push(d);
        } else if (isGeneralPanel(d)) {
          panelsId.push(getId(d));
        } else if (isGroup(d)) {
          const children = getGroupChildren(layersById[d]).map((o) => o.id);
          sperateIds(children);
        }
      });
    };
    sperateIds(layersSelected);

    const childrenId: any = [];

    const componentsDimension = componentsId.reduce((all, item) => {
      const component = componentsById[item];
      if (component) {
        const dimension = getComponentDimension(component.config);
        const children = componentOperator.getChildren(component.id, componentsById);
        if (children && children.length) {
          childrenId.push(...children.map((d) => d.id));
        }
        all.push(dimension);
      }
      return all;
    }, []);
    const panelsDimension = panelsId.map((d) => {
      const panel = panelsById[d];
      const { config } = panel;
      const { width, height, top, left } = config;

      return { width, height, left, top };
    });
    const selectedDimensions = componentsDimension.concat(panelsDimension);
    const minLeft = Math.min(...selectedDimensions.map((d) => d.left));
    const maxRight = Math.max(...selectedDimensions.map((d) => d.left + d.width));
    const minTop = Math.min(...selectedDimensions.map((d) => d.top));
    const maxBottom = Math.max(...selectedDimensions.map((d) => d.top + d.height));
    const centerPoint = [Math.round((minLeft + maxRight) / 2), Math.round((minTop + maxBottom) / 2)];

    const result = await dispatch(
      favoriteCreate({
        name,
        userCategoryId,
        thumb: thumbPath,
        layers: favoriteLayers.map((d) => ({ ...d, path: undefined, groupPath: undefined })),
        components: componentsId,
        children: childrenId,
        panels: panelsId,
        centerPoint
      })
    );

    if (result) {
      dispatch({
        type: actionTypes.FAVORITE_CREATE_SUCCESS,
        payload: result
      });
      return result;
    } else {
      dispatch({
        type: actionTypes.FAVORITE_CREATE_FAILURE
      });
    }
  };
}

export function addFavorite(favoriteId: number, source?: 'platform' | 'official') {
  return async (dispatch, getState) => {
    const hide = message.loading('正在添加组件...', 0);
    const { createApp, screensById } = getState();
    const { id, scale, layersSelected } = createApp;
    const { layers } = screensById[id];

    const { left, top } = getScreenCenter(scale);
    const firstSelectedId = layersSelected.length ? getFirstSelectedId({ layers, selected: layersSelected }) : undefined;

    const result: any = await request(
      api.favoriteAdd,
      undefined,
      undefined,
      JSON.stringify({
        id,
        layerMaterialId: favoriteId,
        centerPoint: [left, top],
        insertId: firstSelectedId,
        source
      })
    );

    if (result) {
      // 如果从收藏中添加的组件，可能带有过滤器，需要添加
      if (result.filters && result.filters.length) {
        const topScreenId = getTopScreenId();
        dispatch({
          type: actionTypes.FILTER_ADD,
          payload: {
            filter: result.filters.map((d) => ({ ...d, screenId: topScreenId }))
          }
        });
      }

      // 追加components
      const addedComponentsById = transformComponents(result.components, id);

      // dispatch({
      //   type: actionTypes.COMPONENTS_ADD,
      //   payload: {
      //     list: Object.keys(addedComponentsById).map((d) => addedComponentsById[d])
      //   }
      // });
      dispatch(commponentsAdd({ list: Object.keys(addedComponentsById).map((d) => addedComponentsById[d]) }));

      // 如果存在动态面板
      const panels = getPanelsFromLayers(result.layers);
      if (panels.length) {
        panels.map((d) => dispatch(getPanelInfoForScreenEdit(getId(d.id))));
      }

      // 更新layers
      // const newLayers = insertLayerById({ layers, layer: result.layers[0], insertId: firstSelectedId });
      dispatch({
        type: actionTypes.LAYER_UPDATE,
        payload: {
          id,
          layers: result.layers
        }
      });

      // 选中添加的layer
      dispatch({
        type: actionTypes.LAYER_SELECT,
        payload: {
          selected: [result.selectedLayerId || result.layers[0].id]
        }
      });
    }

    hide();
  };
}

export function deleteFavorite(id) {
  return async (dispatch) => {
    const result = await http.post(api.favoriteDelete, {
      id
    });

    if (result) {
      dispatch({
        type: actionTypes.FAVORITE_DELETE_SUCCESS,
        payload: id
      });
    }
  };
}

export function updateFavorite({ id, name, thumb }) {
  return async (dispatch) => {
    let thumbPath = thumb ? thumb : undefined;
    if (typeof thumb === 'object' && thumb !== null) {
      const result = await uploadAssets({
        path: `thumb/${thumb.name}`,
        file: thumb
      });
      if (!result) {
        return;
      }
      thumbPath = result;
    }

    const result = await http.post(api.favoriteUpdate, {
      id,
      name,
      thumb: thumbPath
    });

    if (result) {
      dispatch({
        type: actionTypes.FAVORITE_UPDATE_SUCCESS,
        payload: {
          id,
          name,
          thumb: thumbPath
        }
      });
    }
    return result;
  };
}

const initialState = {
  loading: false,
  editLoading: false,
  list: []
};

export default function reducer(state = initialState, { type, payload }) {
  switch (type) {
    case actionTypes.FAVORITE_GET_LIST_START: {
      return { ...state, loading: true };
    }
    case actionTypes.FAVORITE_GET_LIST_SUCCESS: {
      return { ...state, loading: false, list: payload };
    }
    case actionTypes.FAVORITE_GET_LIST_FAILURE: {
      return { ...state, loading: false };
    }
    case actionTypes.FAVORITE_CREATE_START: {
      return { ...state, editLoading: true };
    }
    case actionTypes.FAVORITE_CREATE_SUCCESS: {
      const newList = state.list.concat(payload);
      return { ...state, editLoading: false, list: newList };
    }
    case actionTypes.FAVORITE_CREATE_FAILURE: {
      return { ...state, editLoading: false };
    }
    case actionTypes.FAVORITE_DELETE_SUCCESS: {
      const newList = state.list.filter((d: any) => d.id !== payload);
      return { ...state, list: newList };
    }
    case actionTypes.FAVORITE_UPDATE_SUCCESS: {
      const newList = state.list.map((d: any) => (d.id === payload.id ? { ...d, ...payload } : d));
      return { ...state, list: newList };
    }
    default:
      return state;
  }
}
