/** @jsx jsx */
import * as React from "react";
import css from "@styled-system/css";
import { jsx } from "@emotion/core";
import { GapSizes } from "../utils/System";

type VerticalAlignment = "top" | "middle" | "bottom" | "between" | "around" | "evenly" | "baseline" | "stretch" | "";
type HorizontalAlignment = "left" | "center" | "right" | "between" | "around" | "evenly" | "baseline" | "stretch" |  "";
type FlexDirection = "vertical" | "horizontal";

// Flex

export type FlexProps = {
    children: React.ReactNode;
    direction?: FlexDirection;
    vAlignment?: VerticalAlignment;
    hAlignment?: HorizontalAlignment;
    gap?: GapSizes;
    pad?: GapSizes;
    stretch?: boolean;
    shrink?: boolean;
    fill?: string;
    style?: any;
    onClick?: () => void;
};

const getDirection = (direction?: FlexDirection) => {
    if (direction && direction === "vertical") {
        return {
            flexDirection: "column"
        };
    }
};

const getStretch = (stretch?: boolean) => {
    if (stretch) {
        return {
            "> div": {
                flexBasis: "stretch",
                flexGrow: 1
            }
        };
    }
};

const getShrink = (shrink?: boolean) => {
    if (shrink) {
        return {
            flex: "0 0 auto !important",
            flexGrow: "0 !important"
        };
    }
};

const getGap = (gap: GapSizes, direction?: FlexDirection) => {
    if (gap) {
        if (direction && direction === "vertical") {
            return {
                "> * + *": {
                    marginTop: getGapValue(gap)
                }
            };
        } else {
            return {
                "> * + *": {
                    marginLeft: getGapValue(gap)
                }
            };
        }
    }
};

const getAxis = (hAlignment: HorizontalAlignment, vAlignment: VerticalAlignment, direction: FlexDirection ) => {

    let primaryAxis = '';
    let secondaryAxis = '';

    switch (hAlignment) {
        case 'left':
            primaryAxis = 'flex-start';
            break
        case 'center':
            primaryAxis = 'center';
            break
        case 'right':
            primaryAxis = 'flex-end';
            break
        case 'between':
            primaryAxis = 'space-between';
            break
        case 'around':
            primaryAxis = 'space-around';
            break
        case 'evenly':
            primaryAxis = 'space-evenly';
            break
    }
    if (direction === 'horizontal') {

        switch (vAlignment) {
            case 'top':
                secondaryAxis = 'flex-start';
                break
            case 'middle':
                secondaryAxis = 'center';
                break
            case 'bottom':
                secondaryAxis = 'flex-end';
                break
            
        }
    }
    // if vertical flip it
    if (direction === 'vertical') {
        switch (hAlignment) {
            case 'left':
                secondaryAxis = 'flex-start';
                break
            case 'center':
                secondaryAxis = 'center';
                break
            case 'right':
                secondaryAxis = 'flex-end';
                break
    
        }
        switch (vAlignment) {
            case 'top':
                primaryAxis = 'flex-start';
                break
            case 'middle':
                primaryAxis = 'center';
                break
            case 'bottom':
                primaryAxis = 'flex-end';
                break
            case 'between':
                primaryAxis = 'space-between';
                break
            case 'around':
                primaryAxis = 'space-around';
                break
            case 'evenly':
                primaryAxis = 'space-evenly';
                    break
        }
    }

    return {
        alignItems: secondaryAxis,
        justifyContent: primaryAxis
    }
}

const getCss = (props: FlexProps): any => {
    const { gap = '', direction = "horizontal", stretch, shrink, hAlignment = "", vAlignment = "" } = props;
    return {
        ...getDirection(direction),
        ...getGap(gap, direction),
        ...getStretch(stretch),
        ...getShrink(shrink),
        ...getAxis(hAlignment,vAlignment, direction)
    };
};

const getGapValue = (gap: GapSizes): number => {
    switch (gap) {
        case "small":
            return 2;
        case "medium":
            return 4;
        case "large":
            return 5;
        default:
            break;
    }
    return 0;
};

const Flex: React.FC<FlexProps> = props => {
    const { children, pad, fill, style, onClick } = props;
    return (
        <div
            onClick={!!onClick ? onClick : undefined}
            style={style}
            css={css({
                ...getCss(props),
                display: "flex",
                flex: "1 1 auto",
                // outline: "1px solid magenta",
                padding: `${pad ? getGapValue(pad) : "initial"}`,
                bg: `${fill ? fill : "initial"}`
            })}
        >
            {children && children}
        </div>
    );
};

export default Flex;
