/** @jsx createElement */

'use strict';

import { createElement, Component, findDOMNode, PropTypes } from 'rax';
import View from 'nuke-view';
import { Detection } from 'nuke-ep-utils';
import { connectStyle } from 'nuke-theme-provider';
import Emitter from '../util/emitter';
import stylesProvider from '../styles/index';
import Nav from './nav';
// 在weex及非android4.4以下的机器中才使用ep绑定
let expressionBinding = {};
try {
  expressionBinding = require('@weex-module/expressionBinding');
} catch (e) { }
class Tabbar extends Component {
  constructor(props) {
    super(props);
    this.childrenElements = []; // 存放tab主体element
    this.tabMap = {}; // 用于记录哪个tab是被激活过的状态
    this.tabPage = []; // 存放tab节点
    this.scrolling = false;
    this.maxIndex = (props.children && props.children.length - 1) || 0; // tab的子节点只能是tab.item
    this.state = {
      curIndex:
        props.activeKey &&
          props.activeKey >= 0 &&
          props.activeKey <= this.maxIndex
          ? props.active
          : 0,
      transform: 0,
      prevIndex: null,
    };
    if (
      typeof props.activeKey === 'number' &&
      props.activeKey >= 0 &&
      props.activeKey <= this.maxIndex
    ) {
      this.tabMap[props.activeKey] = true;
    }
  }
  componentWillMount() {
    Emitter.on('scroll', (data) => {
      this.scrolling = true;
      if (this.scrollTimer) {
        clearTimeout(this.scrollTimer);
      }
      this.scrollTimer = setTimeout(() => {
        this.scrolling = false;
      }, 300);
    });
  }
  componentDidMount() {
    if (Detection.epEnable && Detection.iOS && this.props.epEnable) {
      setTimeout(() => {
        const listElement = findDOMNode(this.refs.listSlider);
        if (listElement && listElement.ref) {
          expressionBinding.enableBinding(listElement.ref, 'pan');
        }
      }, 500);
    }
    // hack for android
    if (Detection.epEnable && Detection.Android) {
      Emitter.on('slider', (params) => {
        this.bindExp(params.element);
      });
    }
  }
  /**
   * ep绑定方法
   */
  bindExp = (element) => {
    if (!this.isMoving && element && element.ref && Detection.epEnable) {
      this.startTime = Date.now();
      const { dataSource, navFocusStyle } = this.props;
      const listElement = findDOMNode(this.refs.listSlider);
      const index = this.state.curIndex;
      const tabFocusElement = findDOMNode(
        this.refs.nav.wrappedInstance.refs.tabFocus
      );
      // 绑定滚动只取第一个  itemWidthList的宽度
      const tabItemWidth =
        dataSource[0] && dataSource[0].style && dataSource[0].style.width;
      const dpr = 1;
      const tabLeft = index * tabItemWidth / dpr;
      if (navFocusStyle && navFocusStyle.left) {
        // tabLeft += navFocusStyle.left;
      }
      const sliderLeft = index * 750 / dpr;
      /*
       ep表达式备注
       左边界 min(x, x/3)
       右边界 max(x, x/3) - ${dist}
       中间 x - dist
       */
      const args = [
        {
          element: tabFocusElement.ref,
          property: 'transform.translateX',
          expression: `{\"type\":\"-\",\"children\":[{\"type\":\"NumericLiteral\",\"value\":${tabLeft}},{\"type\":\"/\",\"children\":[{\"type\":\"Identifier\",\"value\":\"x\"},{\"type\":\"NumericLiteral\",\"value\":5}]}]}`,
        },
      ];

      if (index == 0) {
        //  第一帧 min(x, x/3)
        const ep2 =
          '{"type":"CallExpression","children":[{"type":"Identifier","value":"min"},{"type":"Arguments","children":[{"type":"Identifier","value":"x"},{"type":"/","children":[{"type":"Identifier","value":"x"},{"type":"NumericLiteral","value":3}]}]}]}';
        args.push({
          element: listElement.ref,
          property: 'transform.translateX',
          expression: ep2,
        });
      } else if (index == dataSource.length - 1) {
        // 最后一祯 `max(x, x/3) - ${sliderLeft}`
        const ep2 = `{\"type\":\"-\",\"children\":[{\"type\":\"CallExpression\",\"children\":[{\"type\":\"Identifier\",\"value\":\"max\"},{\"type\":\"Arguments\",\"children\":[{\"type\":\"Identifier\",\"value\":\"x\"},{\"type\":\"/\",\"children\":[{\"type\":\"Identifier\",\"value\":\"x\"},{\"type\":\"NumericLiteral\",\"value\":3}]}]}]},{\"type\":\"NumericLiteral\",\"value\":${sliderLeft}}]}`;
        args.push({
          element: listElement.ref,
          property: 'transform.translateX',
          expression: ep2,
        });
      } else {
        // `x - ${sliderLeft}`
        const ep2 = `{\"type\":\"-\",\"children\":[{\"type\":\"Identifier\",\"value\":\"x\"},{\"type\":\"NumericLiteral\",\"value\":${sliderLeft}}]}`;
        args.push({
          element: listElement.ref,
          property: 'transform.translateX',
          expression: ep2,
        });
      }
      // console.log('enableBinding');
      // expressionBinding.enableBinding(element.ref, 'pan');
      // console.log('createBinding');
      expressionBinding.createBinding(
        element.ref,
        'pan',
        '',
        args,
        this.panEnd
      );
    }
  };
  /**
   *  横向滑动事件
   */
  onHorizontalPan = (e) => {
    if (e.state === 'start' && !this.scrolling) {
      const listElement = findDOMNode(this.refs.listSlider);
      this.bindExp(listElement);
    }
  };
  /**
   *  横向滑动停止
   */
  panEnd = (e) => {
    console.log('[debug]:panEnd');
    if (e.state === 'end') {
      const duration = Date.now() - this.startTime;
      const dist = e.deltaX;
      const { curIndex } = this.state;
      const panDist = this.props.panDist ? this.props.panDist : 375;
      let newIndex = curIndex;
      if (
        Math.abs(dist) > panDist ||
        (Math.abs(dist) / duration > 0.5 && duration < 200)
      ) {
        if (dist > 0) {
          newIndex--;
        } else {
          newIndex++;
        }
      }
      if (newIndex < 0) {
        newIndex = 0;
      } else if (newIndex > this.maxIndex) {
        newIndex = this.maxIndex;
      }
      if (Detection.iOS) {
        setTimeout(() => {
          this.slideTo(newIndex, 'pan');
        }, 50);
      } else {
        this.slideTo(newIndex, 'pan');
      }
    }
  };
  /**
   * tab切换前的回调函数
   * @param index 即将滚动去的位置
   * @param type  触发滚动的事件类型
   */
  slideTo = (index, type) => {
    const time = 300;
    if (this.isMoving === true) return;
    this.isMoving = true;
    const { onChange, beforeSlide, forbidNavScroll } = this.props;
    const prevIndex = this.state.curIndex;
    const moveEndCallback = () => {
      if (typeof onChange === 'function') {
        onChange(index, prevIndex, type);
      }
      this.setState({
        curIndex: index,
        prevIndex,
      });
      this.isMoving = false;
    };
    const navRef = this.refs.nav && this.refs.nav.wrappedInstance;
    if (typeof beforeSlide === 'function') {
      if (!beforeSlide(index, type)) return;
    }
    // 选中状态滚动,当只有两个item，无需scroll的时候需要禁止滚动
    if (!forbidNavScroll) {
      navRef.scrollTo(index);
    }
    navRef.focusMove(index);
    navRef.setState({
      curIndex: index,
    });
    if (Detection.epEnable) {
      // 高版本系统的手机才使用transform动画
      const animation = require('@weex-module/animation');
      const sliderElement = this.refs.listSlider;
      const dist = 750 * index;
      animation.transition(
        findDOMNode(sliderElement),
        {
          styles: {
            transform: `translateX(-${dist}px)`,
          },
          delay: 0,
          duration: time,
          timingFunction: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)', // ['cubic-bezier(0.25, 0.46, 0.45, 0.94)', 'cubic-bezier(0,0,0.25,1)']
        },
        () => { }
      );
    }
    moveEndCallback();
  };
  render() {
    const { curIndex, prevIndex } = this.state;
    const {
      themeStyle,
      children,
      style,
      navTop,
      dataSource,
      renderNavItem,
      navStyle,
      renderLoading,
      navFocusStyle,
      forceRender, // ignore SCU just forceRender
      navContentStyle,
    } = this.props;
    const { slider } = themeStyle;
    if (!children.length) {
      return null;
    }
    if (navTop) {
      slider.top = navStyle && navStyle.height;
      navStyle.top = 0;
      delete navStyle.bottom;
    } else {
      slider.bottom = navStyle && navStyle.height;
      navStyle.bottom = 0;
      delete navStyle.top;
    }
    // 根据子节点计算tab偏移

    const sliderStyle = [slider];
    if (Detection.epEnable) {
      sliderStyle.push({
        width: 750 * children.length,
      });
      if (Detection.iOS) {
        sliderStyle.push({
          transform: `translateX(-${750 * this.state.curIndex})`,
        });
      }
      if (this.tabMap[curIndex]) {
        this.tabMap[curIndex]++;
      } else {
        this.tabMap[curIndex] = 1;
      }
    }
    let formatChildren = [];
    if (Detection.epEnable) {
      formatChildren = children.map((child, index) => {
        const length = children.length;
        const next = circleIndex(this.state.curIndex + 1, length);
        const prev = circleIndex(this.state.curIndex - 1, length);
        const shouldRender = this.tabMap[index] === 1;
        const eachTabStyle = [themeStyle.eachTab, { left: 750 * index }];
        if (this.tabMap[index] && curIndex === index) {
          this.tabPage[curIndex] = (
            <View style={eachTabStyle} key={index} shouldRender={shouldRender}>
              {child}
            </View>
          );
        }
        if (this.tabMap[index]) {
          return this.tabPage[index];
        }
        if (
          typeof renderLoading === 'function' &&
          (index === next || index === prev)
        ) {
          return (
            <View style={eachTabStyle} key={index}>
              {renderLoading(index)}
            </View>
          );
        }
        return null;
      });
    } else {
      formatChildren = children.map((child, index) => {
        if (index === curIndex) {
          return child;
        }
        return null;
      });
    }
    const childrenElements = [
      <View
        style={sliderStyle}
        ref="listSlider"
        onHorizontalPan={
          Detection.epEnable && Detection.iOS && this.props.epEnable
            ? this.onHorizontalPan
            : null
        }
      >
        {formatChildren}
      </View>,
    ];
    const headerStyle = navTop
      ? {
        ...navStyle,
        top: 0,
        positon: 'relative',
      }
      : navStyle;
    const NavWithProps = (
      <View style={[themeStyle.header, headerStyle]}>
        <Nav
          ref="nav"
          dataSource={dataSource}
          renderNavItem={renderNavItem}
          slideTo={(...args) => this.slideTo(...args)}
          style={navStyle}
          contentStyle={navContentStyle}
          navFocusStyle={navFocusStyle}
          forceRender={forceRender}
        />
      </View>
    );
    navTop
      ? childrenElements.unshift(NavWithProps)
      : childrenElements.push(NavWithProps);
    return (
      <View style={[themeStyle.wrapContainer, style]}>{childrenElements}</View>
    );
  }
}
function circleIndex(i, len) {
  return (len + i % len) % len;
}
// Tabbar.propTypes = {
// };

Tabbar.defaultProps = {
  epEnable: false,
  navTop: true,
};
Tabbar.displayName = 'Ep-Tabbar';

export default connectStyle(stylesProvider)(Tabbar);
