/*
* This file implements a basic drawer control.
*/

import RX = require('reactxp');
interface MainPanelProps extends RX.CommonStyledProps<RX.Types.ViewStyleRuleSet> {
    renderDrawer: () => JSX.Element;
    renderContent: () => JSX.Element;
}

// Duration (in ms) of drawer animation.
const animationDuration = 250;

// Amount that the content panel should "peek out" when the
// drawer is open, measured in pixels.
const contentPeekAmount = 100;

const styles = {
    container: RX.Styles.createViewStyle({
        flex: 1,
        alignSelf: 'stretch'
    }),
    drawerContainer: RX.Styles.createViewStyle({
        position: 'absolute',
        marginLeft: contentPeekAmount,
        top: 0,
        right: 0,
        bottom: 0,
        left: 0
    }),
    contentContainer: RX.Styles.createViewStyle({
        position: 'absolute',
        top: 0,
        right: 0,
        bottom: 0,
        left: 0
    })
};

class MainPanel extends RX.Component<MainPanelProps, null> {
    private _drawerShown = false;
    private _viewWidth: number = 0;

    private _animation: RX.Types.Animated.CompositeAnimation;
    private _drawerTranslationValue: RX.Animated.Value;
    private _contentTranslationValue: RX.Animated.Value;
    private _animatedDrawerStyle: RX.Types.AnimatedViewStyleRuleSet;
    private _animatedContentStyle: RX.Types.AnimatedViewStyleRuleSet;

    toggleDrawer() {
        this._drawerShown = !this._drawerShown;

        if (this._animation) {
            this._animation.stop();
        }

        this._animation = RX.Animated.parallel([
            RX.Animated.timing(this._drawerTranslationValue, {
                toValue: this._drawerShown ? -contentPeekAmount : -this._viewWidth,
                easing: RX.Animated.Easing.InOut(),
                duration: animationDuration
            }),
            RX.Animated.timing(this._contentTranslationValue, {
                toValue: this._drawerShown ? this._viewWidth - contentPeekAmount : 0,
                easing: RX.Animated.Easing.InOut(),
                duration: animationDuration
            })
        ]);
        
        this._animation.start(() => {
            this._animation = null;
        });
    }

    constructor(props: MainPanelProps) {
        super(props);

        this._drawerTranslationValue = new RX.Animated.Value(0);
        this._animatedDrawerStyle = RX.Styles.createAnimatedViewStyle({
            transform: [
                {
                    translateX: this._drawerTranslationValue
                }
            ]
        });

        this._contentTranslationValue = new RX.Animated.Value(0);
        this._animatedContentStyle = RX.Styles.createAnimatedViewStyle({
            transform: [
                {
                    translateX: this._contentTranslationValue
                }
            ]
        });
    }

    private _onLayout = (layoutInfo: RX.Types.LayoutInfo) => {
        this._viewWidth = layoutInfo.width;

        // Stop any animation.
        if (this._animation) {
            this._animation.stop();
        }

        // Immediately update animation values for new width.
        this._drawerTranslationValue.setValue(this._drawerShown ? -contentPeekAmount : -this._viewWidth);
        this._contentTranslationValue.setValue(this._drawerShown ? this._viewWidth - contentPeekAmount : 0);
    }

    render() {
        return (
            <RX.View style={ [styles.container, this.props.style] } onLayout={ this._onLayout }>
                <RX.Animated.View style={ [styles.drawerContainer, this._animatedDrawerStyle] }>
                    { this.props.renderDrawer() }
                </RX.Animated.View>
                <RX.Animated.View style={ [styles.contentContainer, this._animatedContentStyle] }>
                    { this.props.renderContent() }
                </RX.Animated.View>
            </RX.View>
        );
    }
}

export = MainPanel;
