/* eslint-disable react/no-did-update-set-state  */
/**
 * Album Component for uxcore
 * @author vincent.bian
 *
 * Copyright 2015-2016, Uxcore Team, Alinw.
 * All rights reserved.
 */
import React from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
import classnames from 'classnames';
import assign from 'object-assign';
import Animate from 'uxcore-animate';
import { polyfill } from 'react-lifecycles-compat';
import { supportRGBA } from './rgba-detect';
import Viewer from './Viewer';
import Photo from './Photo';
import Carousel from './Carousel';

class Album extends React.Component {
  static getDerivedStateFromProps(props, state) {
    if (props.current !== state.lastIndex) {
      return {
        ...state,
        current: props.current,
        lastIndex: props.current,
      };
    }
    return null;
  }

  constructor(props) {
    super(props);
    this.state = {
      open: false,
      current: props.current,
      left: 0,
      top: 0,
      lastIndex: props.current,
    };

    this.openAlbum = this.openAlbum.bind(this);
    this.prev = this.prev.bind(this);
    this.next = this.next.bind(this);
    this.setCurrent = this.setCurrent.bind(this);
  }


  setCurrent(i) {
    this.setState({
      current: i,
    });
  }


  /**
   * 切换图片
   */
  handleChange() {
    const { onChange } = this.props;
    const { current } = this.state;
    if (typeof onChange === 'function') {
      onChange(current);
    }
  }

  /**
   * 打开大图
   */
  handleOpen() {
    const { onOpen } = this.props;
    const { current } = this.state;
    if (typeof onOpen === 'function') {
      onOpen(current);
    }
  }

  /**
   * 关闭大图
   */
  handleCloce() {
    const { onClose } = this.props;
    if (typeof onClose === 'function') {
      onClose();
    }
  }

  prev() {
    const current = this.state.current;
    if (current === 0) return;
    this.setState({
      current: current - 1,
    }, () => {
      this.handleChange();
    });
  }

  next() {
    const current = this.state.current;
    let { children } = this.props;
    if (!Array.isArray(children)) {
      children = [children];
    }
    if (current === children.length - 1) return;
    this.setState({
      current: current + 1,
    }, () => {
      this.handleChange();
    });
  }

  openAlbum() {
    this.setState({
      open: true,
    });
    this.handleOpen();
  }

  renderAlbum() {
    const { current, open } = this.state;
    const {
      enableKeyBoardControl, showButton, customButtons, maskClosable,
    } = this.props;
    let { children } = this.props;
    if (!Array.isArray(children)) {
      children = [children];
    }
    let rect;
    let coordinate;
    if (this.cover && this.cover.img && this.cover.img.getBoundingClientRect) {
      rect = this.cover.img.getBoundingClientRect();
    }
    if (rect) {
      coordinate = {
        left: rect.left,
        top: rect.top,
        width: rect.width,
        height: rect.height,
      };
    }
    return (
      <Animate
        component=""
        transitionName="album-overlay"
        transitionAppear
        transitionEnter
        transitionLeave
        showProp="open"
      >
        <Viewer
          key="viewer"
          prev={this.prev}
          next={this.next}
          onChange={this.handleChange.bind(this)}
          onClose={(e) => {
            if (e) {
              e.preventDefault();
              this.setState({
                open: false,
              });
              this.handleCloce();
            }
          }}
          maskClosable={maskClosable}
          enableKeyBoardControl={enableKeyBoardControl}
          ref={(node) => { this.viewer = node; }}
          coordinate={coordinate}
          showButton={showButton}
          customButtons={customButtons}
          current={current}
          open={open}
          onSetCurrent={(c) => {
            this.setState({ current: c });
          }}
        >
          {children}
        </Viewer>
      </Animate>
    );
  }

  renderCover() {
    const {
      width, height, children, enableThumbs, thumbBackground,
    } = this.props;
    const { current } = this.state;
    const coverStyle = {};
    if (width) {
      coverStyle.width = width;
    }
    if (height) {
      coverStyle.height = height;
    }
    if (enableThumbs) {
      coverStyle.background = thumbBackground;
    }

    return (
      <div>
        <div
          className="album-cover album-icon"
          onClick={this.openAlbum}
          style={coverStyle}
        >
          {React.Children.map(children, (child, index) => {
            if (index === current) {
              return React.cloneElement(child, {
                ref: (cover) => { this.cover = cover; },
              });
            }
            return null;
          })}
        </div>
        {enableThumbs ? this.renderThumbs() : ''}
      </div>
    );
  }

  renderThumbs() {
    const {
      thumbPlacement, children, width, height,
    } = this.props;
    const { current } = this.state;
    const isHorizontal = thumbPlacement === 'right' || thumbPlacement === 'left';
    const thumbs = React.Children.map(children, (o) => {
      const src = o.props['thumb-src'] || o.props.src;
      return (
        <div key={src} className="album-item">
          <img src={src} alt="" />
        </div>
      );
    });
    const carouselStyle = isHorizontal ? {
      height,
      width: 122,
    } : {
        height: 72,
        width,
      };
    const containerStyle = isHorizontal ? {
      height: height - 50,
      width: 122,
    } : {
        height: 72,
        width: width - 50,
      };
    return (
      <Carousel
        current={current}
        placement={thumbPlacement}
        onPrev={this.prev}
        onNext={this.next}
        onSetCurrent={this.setCurrent}
        itemSize={isHorizontal ? 78 : 126}
        className="thumbs-preview"
        onChange={this.handleChange.bind(this)}
        carouselStyle={carouselStyle}
        containerStyle={containerStyle}
      >
        {thumbs}
      </Carousel>
    );
  }

  render() {
    const {
      prefixCls, enableThumbs, thumbPlacement, width, height,
    } = this.props;
    const isHorizontal = thumbPlacement === 'right' || thumbPlacement === 'left';
    const style = isHorizontal ? {
      width: width + (enableThumbs ? 140 : 10),
    } : {
        height: height + (enableThumbs ? 90 : 10),
      };

    return (
      <div
        className={classnames(prefixCls, {
          'no-rgba': !supportRGBA,
          'has-thumb': enableThumbs,
          [`thumb-placement-${thumbPlacement}`]: enableThumbs,
        })}
        style={style}
        ref={(node) => { this.wrap = node; }}
      >
        {
          this.renderCover()
        }
        {
          this.renderAlbum()
        }
      </div>
    );
  }
}

Album.defaultProps = {
  prefixCls: 'kuma-uxcore-album',
  width: '',
  height: '',
  thumbPlacement: 'right',
  thumbBackground: '#000',
  enableThumbs: false,
  enableKeyBoardControl: true,
  showButton: false,
  customButtons: Viewer.defaultProps.customButtons,
  current: 0,
};


// http://facebook.github.io/react/docs/reusable-components.html
Album.propTypes = {
  prefixCls: PropTypes.string,
  width: PropTypes.number,
  height: PropTypes.number,
  thumbPlacement: PropTypes.string,
  thumbBackground: PropTypes.string,
  enableThumbs: PropTypes.bool,
  enableKeyBoardControl: PropTypes.bool,
  showButton: PropTypes.bool,
  customButtons: Viewer.propTypes.customButtons,
  children: PropTypes.node,
  current: PropTypes.number,
};

Album.displayName = 'Album';

Album.show = (option = {}) => {
  const config = {
    src: null,
    photos: [],
    current: 0,
    getContainer() {
      const container = document.createElement('div');
      document.body.appendChild(container);
      return container;
    },
  };
  assign(config, option);
  if (!config.src && config.photos.length === 0) {
    // eslint-disable-next-line
    console.warn('You must provide valid parameters: "src" or "photos"!');
  }
  const container = config.getContainer();
  let photos;
  if (config.src) {
    photos = [<Photo src={config.src} key={0} />];
  } else {
    photos = config.photos;
  }
  let hasControl = false;
  if (photos.length > 1) {
    hasControl = true;
  }

  /**
   * 切换
   * @param {Number} index
   */
  const handleChange = (index) => {
    if (typeof config.onChange === 'function') {
      config.onChange(index);
    }
  };

  /**
   * 关闭
   */
  const handleCloce = () => {
    if (typeof config.onClose === 'function') {
      config.onClose();
    }
  };

  const prefixCls = option.prefixCls || 'kuma-uxcore-album';

  ReactDOM.render(
    <div
      className={classnames(prefixCls, {
        'no-rgba': !supportRGBA,
      })}
      tabIndex="-1"
    >
      <Animate
        component=""
        transitionName="album-overlay"
        transitionAppear
        transitionEnter
        transitionLeave
      >
        <Viewer
          onClose={() => {
            handleCloce();
            document.body.removeChild(container);
          }}
          current={config.current}
          hasControl={hasControl}
          showButton={config.showButton}
          customButtons={config.customButtons}
          onChange={handleChange}
          maskClosable={config.maskClosable}
        >
          {photos}
        </Viewer>
      </Animate>
    </div>,
    container,
  );
};

polyfill(Album);

export default Album;
