import _mergeJSXProps from 'babel-helper-vue-jsx-merge-props';
import _extends from 'babel-runtime/helpers/extends';
import shallowEqual from 'shallowequal';
import omit from 'omit.js';
import { getOptionProps } from '../props-util';
import PropTypes from '../vue-types';

function getDisplayName(WrappedComponent) {
  return WrappedComponent.name || 'Component';
}

var defaultMapStateToProps = function defaultMapStateToProps() {
  return {};
};
export default function connect(mapStateToProps) {
  var shouldSubscribe = !!mapStateToProps;
  var finnalMapStateToProps = mapStateToProps || defaultMapStateToProps;
  return function wrapWithConnect(WrappedComponent) {
    var tempProps = omit(WrappedComponent.props || {}, ['store']);
    var props = {};
    Object.keys(tempProps).forEach(function (k) {
      props[k] = PropTypes.any;
    });
    var Connect = {
      name: 'Connect_' + getDisplayName(WrappedComponent),
      props: props,
      inject: {
        storeContext: { 'default': {} }
      },
      data: function data() {
        this.store = this.storeContext.store;
        return {
          subscribed: finnalMapStateToProps(this.store.getState(), this.$props)
        };
      },

      watch: {},
      mounted: function mounted() {
        this.trySubscribe();
      },
      beforeDestroy: function beforeDestroy() {
        this.tryUnsubscribe();
      },

      methods: {
        handleChange: function handleChange() {
          if (!this.unsubscribe) {
            return;
          }

          var nextState = finnalMapStateToProps(this.store.getState(), this.$props);
          if (!shallowEqual(this.subscribed, nextState)) {
            this.subscribed = nextState;
          }
        },
        trySubscribe: function trySubscribe() {
          if (shouldSubscribe) {
            this.unsubscribe = this.store.subscribe(this.handleChange);
            this.handleChange();
          }
        },
        tryUnsubscribe: function tryUnsubscribe() {
          if (this.unsubscribe) {
            this.unsubscribe();
            this.unsubscribe = null;
          }
        },
        getWrappedInstance: function getWrappedInstance() {
          return this.$refs.wrappedInstance;
        }
      },
      render: function render() {
        var h = arguments[0];
        var $listeners = this.$listeners,
            _$slots = this.$slots,
            $slots = _$slots === undefined ? {} : _$slots,
            $attrs = this.$attrs,
            $scopedSlots = this.$scopedSlots,
            subscribed = this.subscribed,
            store = this.store;

        var props = getOptionProps(this);
        var wrapProps = {
          props: _extends({}, props, subscribed, {
            store: store
          }),
          on: $listeners,
          attrs: $attrs,
          scopedSlots: $scopedSlots
        };
        return h(
          WrappedComponent,
          _mergeJSXProps([wrapProps, { ref: 'wrappedInstance' }]),
          [Object.keys($slots).map(function (name) {
            return h(
              'template',
              { slot: name },
              [$slots[name]]
            );
          })]
        );
      }
    };
    return Connect;
  };
}