// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

import PropTypes from 'prop-types';

import React from "react";
import {Overlay} from 'react-bootstrap';
import {TransitionMotion, spring} from 'react-motion';

export class TrayContents extends React.Component {
  static propTypes = {
    contentVisible: PropTypes.bool.isRequired,
    closeTray: PropTypes.func.isRequired,
    onEnter: PropTypes.func,
    container: PropTypes.object
  };

  static defaultProps = {
    onEnter: () => {}
  };

  constructor (props) {
    super(props);
    if (!props.container) {
      this.container = this;
    }
  }

  getChildren = (items) => {
    const {style} = items[0];
    const className = "tray show-tray " + this.props.className;
    return (
      <div key={'1'} id={this.props.id} style={{opacity: style.opacity, top: style.top + 'px'}} className={className}>
        {this.props.children}
      </div>);
  };

  willEnter = () => {
    return {
      opacity: spring(1),
      top: spring(64)
    };
  };

  willLeave = () => {
    return {
      opacity: spring(0),
      top: spring(30)
    };
  };

  getDefaultStyles = () => {
    return [{key: '1', style: {opacity: 0, top: 30}}];
  };

  getStyles = (prevStyle) => {
    if (!prevStyle) {
      return [{
        key: '1',
        style: this.willEnter()
      }];
    }
    return prevStyle.map(item => {
      return {
        key: '1',
        style: item.style
      };
    });
  };

  render() {
    return (
      <Overlay
        show={this.props.contentVisible}
        onHide={this.props.closeTray}
        placement={"bottom"}
        target={this.props.container}
        rootClose={true}
        onEnter={this.props.onEnter}
      >
        <TransitionMotion
          defaultStyles={this.getDefaultStyles()}
          styles={this.getStyles()}
          willLeave={this.willLeave}
          willEnter={this.willEnter}
        >
          {this.getChildren}
        </TransitionMotion>
      </Overlay>
    );
  }
}


export const connectToStores = (Component, stores, getStateFromStores) => {
  class WrappingElement extends React.Component {
    state = getStateFromStores(this.props);

    componentDidMount() {
      stores.forEach(store => {
        store.on('change', this.onChange, this);
      });
    }

    componentWillUnmount() {
      stores.forEach(function (store) {
        store.off('change', this.onChange);
      }.bind(this));
    }

    onChange = () => {
      this.setState(getStateFromStores(this.props));
    };

    handleStoresChanged = () => {
      this.setState(getStateFromStores(this.props));
    };

    render() {
      return <Component {...this.state} {...this.props} />;
    }
  }

  return WrappingElement;
};

export class TrayWrapper extends React.Component {
  static defaultProps = {
    className: ''
  };

  renderChildren = () => {
    return React.Children.map(this.props.children, (child) => {

      const props = {};
      Object.keys(this.props).filter((k) => {
        return Object.prototype.hasOwnProperty.call(this.props, k);
      }).map((k) => {
        return props[k] = this.props[k];
      });

      return React.cloneElement(child, props);
    });
  };

  render() {
    return (
      <div>
        {this.renderChildren()}
      </div>
    );
  }
}
