import { timeout } from 'promise-timeout';
import { BaseActionTrigger } from './types';
import { componentNodeMap, getComponentNode } from '../componentNodeMap';
import { getComponentInstance } from '../instanceMap';

export function pipeActions(iActions) {
  return async ({ meta, global }) => {
    for (const {
      action: { action, maxTimeout = 10 * 1000 },
      key,
      data,
      target,
    } of iActions) {
      const params = {
        data,
        key,
        global,
        meta,
        componentsMap: componentNodeMap,
        getComponentByKey: getComponentNode,
        target,
      };

      if (typeof target === 'number') {
        Object.defineProperty(params, 'target', {
          get() {
            return {
              key: target,
              get instance() {
                return getComponentInstance(target);
              },
              get node() {
                return getComponentNode(target);
              },
            };
          },
        });
      }

      try {
        if (maxTimeout === 'Infinity') {
          await action(params);
        } else {
          const p = action(params);
          if (p instanceof Promise) {
            await timeout(action(params), maxTimeout);
          }
        }
      } catch (e) {
        console.error('Action throw error: ', e);
      }
    }
  };
}

export function generateHandler(actions, trigger) {
  if (!actions || !actions.length) {
    return undefined;
  }

  const iActions = actions.filter(a => a.trigger === trigger);
  if (!iActions.length) {
    return undefined;
  }

  return pipeActions(iActions);
}

export function generateHandlers(actions) {
  const handlers = {};

  const onInit = generateHandler(actions, BaseActionTrigger.INIT);
  if (onInit) {
    handlers.onInit = onInit;
  }

  const onClick = generateHandler(actions, BaseActionTrigger.CLICK);
  if (onClick) {
    handlers.onClick = onClick;
  }

  const onMouseEnter = generateHandler(actions, BaseActionTrigger.MOUSE_ENTER);
  if (onMouseEnter) {
    handlers.onMouseEnter = onMouseEnter;
  }

  const onMouseLeave = generateHandler(actions, BaseActionTrigger.MOUSE_LEAVE);
  if (onMouseLeave) {
    handlers.onMouseLeave = onMouseLeave;
  }

  const onDoubleClick = generateHandler(actions, BaseActionTrigger.DOUBLE_CLICK);
  if (onDoubleClick) {
    handlers.onDoubleClick = onDoubleClick;
  }

  const onLongPress = generateHandler(actions, BaseActionTrigger.LONG_PRESS);
  if (onLongPress) {
    handlers.onLongPress = onLongPress;
  }

  const onEnterView = generateHandler(actions, BaseActionTrigger.ENTER_VIEW);
  if (onEnterView) {
    handlers.onEnterView = onEnterView;
  }

  const onLeaveView = generateHandler(actions, BaseActionTrigger.LEAVE_VIEW);
  if (onLeaveView) {
    handlers.onLeaveView = onLeaveView;
  }

  return handlers;
}
