// @flow
import type { StackeeProps, StackeeOptions } from './stackee.proptypes';
import {
  breakPoints,
  type BreakPoint,
  bpMedium,
  bpLarge,
  bpXLarge,
} from '../../breakpoints';

const getStackeeOptions = ({ grow, shrink, basis }: StackeeOptions): string => {
  const rules = [];

  if (grow != null) {
    rules.push(`flex-grow: ${grow};`);
  }

  if (shrink != null) {
    rules.push(`flex-shrink: ${shrink};`);
  }

  if (basis != null) {
    rules.push(`flex-basis: ${basis}px;`);
  }

  return rules.join(' ');
};

export const getStackeeRules = (stackeeProps: StackeeProps): string => {
  const rules = [];

  const globalOptions: StackeeOptions = {
    grow: typeof stackeeProps.grow === 'number' ? stackeeProps.grow : undefined,
    shrink:
      typeof stackeeProps.shrink === 'number' ? stackeeProps.shrink : undefined,
    basis:
      typeof stackeeProps.basis === 'number' ? stackeeProps.basis : undefined,
  };

  rules.push(getStackeeOptions(globalOptions));

  const optionsByBreakpoint: {
    [BreakPoint]: StackeeOptions,
  } = breakPoints.reduce((acc, bp) => {
    if (
      (stackeeProps.grow instanceof Object && stackeeProps.grow?.[bp]) ||
      (stackeeProps.shrink instanceof Object && stackeeProps.shrink?.[bp]) ||
      (stackeeProps.basis instanceof Object && stackeeProps.basis?.[bp])
    ) {
      acc[bp] = {
        grow:
          stackeeProps.grow instanceof Object
            ? stackeeProps.grow?.[bp]
            : undefined,
        shrink:
          stackeeProps.shrink instanceof Object
            ? stackeeProps.shrink?.[bp]
            : undefined,
        basis:
          stackeeProps.basis instanceof Object
            ? stackeeProps.basis?.[bp]
            : undefined,
      };
    }

    return acc;
  }, {});

  if (optionsByBreakpoint.sm) {
    rules.push(
      `@media (max-width: ${bpMedium}) {${getStackeeOptions(
        optionsByBreakpoint.sm,
      )}}`,
    );
  }

  if (optionsByBreakpoint.md) {
    rules.push(
      `@media (min-width: ${bpMedium}) {${getStackeeOptions(
        optionsByBreakpoint.md,
      )}}`,
    );
  }

  if (optionsByBreakpoint.lg) {
    rules.push(
      `@media (min-width: ${bpLarge}) {${getStackeeOptions(
        optionsByBreakpoint.lg,
      )}}`,
    );
  }

  if (optionsByBreakpoint.xl) {
    rules.push(
      `@media (min-width: ${bpXLarge}) {${getStackeeOptions(
        optionsByBreakpoint.xl,
      )}}`,
    );
  }

  return rules.join('\n');
};
