import React        from 'react';
import AnimakitBase from 'animakit-core';

export default class AnimakitElastic extends AnimakitBase {
  static propTypes = {
    children: React.PropTypes.any,
    duration: React.PropTypes.number,
    easing:   React.PropTypes.string,
  };

  static defaultProps = {
    duration: 500,
    easing:   'cubic-bezier(0.68, -0.55, 0.265, 1.55)',
  };

  state = {
    contentWidth:  null,
    contentHeight: null,
    parentWidth:   null,
    parentHeight:  null,
    animation:     false,
  };

  init() {
    this.parentNode     = document.body;
    this.scrollbarWidth = this.getScrollbarWidth();

    this.contentNode    = null;
    this.contentMounted = false;
  }

  getDuration() {
    return this.props.duration + 1;
  }

  getRootStyles() {
    if (!this.state.animation && !this.props.children) return {};

    const { contentWidth, contentHeight } = this.state;

    const position = 'relative';
    const overflow = 'hidden';

    const width = contentWidth !== null ? `${contentWidth}px` : 'auto';
    const height = contentHeight !== null ? `${contentHeight}px` : 'auto';

    if (!this.state.animation) {
      return { position, overflow, width, height };
    }

    const { duration, easing } = this.props;
    const transition = `width ${duration}ms ${easing}, height ${duration}ms ${easing}`;

    return { position, overflow, width, height, transition };
  }

  getContainerStyles() {
    if (!this.state.animation && !this.props.children) return {};

    const position = 'absolute';

    const { parentWidth, parentHeight } = this.state;

    const width = parentWidth !== null ? `${parentWidth}px` : 'auto';
    const height = parentHeight !== null ? `${parentHeight}px` : 'auto';

    return { position, width, height };
  }

  getContentStyles() {
    if (!this.state.animation && !this.props.children) return {};

    const position = 'absolute';

    return { position };
  }

  getChildrenCount(children) {
    const length = Array.isArray(children) ? children.length : 1;

    if (length > 1) return length;

    return children ? 1 : 0;
  }

  calcContentDimensions(childrenCount) {
    if (!childrenCount) return [0, 0];

    const contentWidth  = this.contentNode.offsetWidth;
    const contentHeight = this.contentNode.offsetHeight;

    return [contentWidth, contentHeight];
  }

  calcParentDimensions(childrenCount) {
    if (!childrenCount) return [0, 0];

    const rect = this.contentNode.getBoundingClientRect();

    const parentWidth  = this.parentNode.offsetWidth - rect.left - this.scrollbarWidth;
    const parentHeight = this.parentNode.offsetHeight - rect.top - this.scrollbarWidth;

    return [parentWidth, parentHeight];
  }

  resetDimensionsState(stateChunk) {
    const { contentWidth, contentHeight, parentWidth, parentHeight } = stateChunk;

    if (
      contentWidth === this.state.contentWidth &&
      contentHeight === this.state.contentHeight &&
      parentWidth === this.state.parentWidth &&
      parentHeight === this.state.parentHeight
    ) return {};

    return stateChunk;
  }

  repaint(props) {
    const childrenCount = this.getChildrenCount(props.children);

    const [contentWidth, contentHeight] = this.calcContentDimensions(childrenCount);
    const [parentWidth, parentHeight] = this.calcParentDimensions(childrenCount);

    const state = this.resetDimensionsState({ contentWidth, contentHeight, parentWidth, parentHeight });

    if (!Object.keys(state).length) return;

    state.animation = this.contentMounted;

    if (this.state.parentWidth === null) {
      setTimeout(() => {
        this.contentMounted = true;
      }, 1);
    }

    this.applyState(state);
  }

  render() {
    return (
      <div style = { this.getRootStyles() }>
        <div style = { this.getContainerStyles() }>
          <div
            style = { this.getContentStyles() }
            ref = {(c) => { this.contentNode = c; }}
          >
          { this.props.children }
          </div>
        </div>
      </div>
    );
  }
}

@@ -2099,31 +2099,24 @@
 %0A  %7D%0A%0A  calc
-Content
 Dimensions(c
@@ -2157,32 +2157,38 @@
 ount) return %5B0,
+ 0, 0,
  0%5D;%0A%0A    const 
@@ -2176,24 +2176,87 @@
  0, 0%5D;%0A%0A   
+ const rect = this.contentNode.getBoundingClientRect();%0A%0A    //
  const conte
@@ -2295,24 +2295,27 @@
 etWidth;%0A   
+ //
  const conte
@@ -2361,24 +2361,22 @@
 t;%0A%0A    
-return %5B
+const 
 contentW
@@ -2383,167 +2383,82 @@
 idth
-, contentHeight%5D;%0A  %7D%0A%0A  calcParentDimensions(childrenCount) %7B%0A    if (!childrenCount) return %5B0, 0%5D;%0A%0A    const rect = this.contentNode.getBoundingClientRect(
+  = Math.ceil(rect.width);%0A    const contentHeight = Math.ceil(rect.height
 );%0A%0A
@@ -2646,16 +2646,45 @@
 return %5B
+contentWidth, contentHeight, 
 parentWi
@@ -3208,66 +3208,10 @@
 ight
-%5D = this.calcContentDimensions(childrenCount);%0A    const %5B
+, 
 pare
@@ -3248,14 +3248,8 @@
 calc
-Parent
 Dime

Fix fractional size bug