import _ from 'lodash';
import { ComponentType, forwardRef, PropsWithChildren } from 'react';
import { Constraints, Measure, Placeable, Layout, useBluefishLayout, withBluefish, LayoutFn } from '../bluefish';
import { NewBBoxClass } from '../NewBBox';

export type VerticalAlignment = 'top' | 'middle' | 'bottom';

export type RowProps = ({ spacing: number } | { totalWidth: number } | { spacing: number; totalWidth: number }) & {
  x?: number;
  y?: number;
  alignment: VerticalAlignment;
};

const rowMeasurePolicy =
  (options: RowProps): Measure =>
  (measurables, constraints: Constraints) => {
    console.log('[row] measure policy called', options);
    let placeables;
    if ('totalWidth' in options && 'spacing' in options) {
      // width is completely determined by the totalWidth and spacing, so update the constraints
      placeables = measurables.map((measurable) =>
        measurable.measure({
          ...constraints,
          width: (options.totalWidth - options.spacing * (measurables.length - 1)) / measurables.length,
        }),
      );
    } else {
      placeables = measurables.map((measurable) => measurable.measure(constraints));
    }

    // alignment
    const height = _.max(_.map(placeables, 'height')) ?? 0;

    switch (options.alignment) {
      case 'top':
        placeables.forEach((placeable) => {
          placeable.top = 0;
        });
        break;
      case 'middle':
        placeables.forEach((placeable) => {
          placeable.top = (height - placeable.height!) / 2;
        });
        break;
      case 'bottom':
        placeables.forEach((placeable) => {
          placeable.top = height - placeable.height!;
        });
        break;
    }

    // spacing
    const width =
      'totalWidth' in options
        ? options.totalWidth
        : _.sumBy(placeables, 'width') + options.spacing * (placeables.length - 1);

    let spacing: number;
    if ('spacing' in options) {
      spacing = options.spacing;
    } else {
      const occupiedWidth = _.sumBy(placeables, 'width');
      spacing = (options.totalWidth - occupiedWidth) / (placeables.length - 1);
    }

    if ('totalWidth' in options && 'spacing' in options) {
      placeables.forEach((placeable, index) => {
        placeable.width = (width - spacing * (placeables.length - 1)) / placeables.length;
      });
    }

    console.log('[row] width', width);
    console.log('[row] spacing', spacing);

    let x = 0;
    placeables.forEach((placeable) => {
      console.log('[row] placing before', placeable.left);
      placeable.left = x;
      console.log('[row] placing after', placeable.left);
      x += placeable.width! + spacing;
    });

    return {
      left: 0,
      top: _.minBy(placeables, 'top')?.top ?? 0,
      width,
      height,
    };
  };

export const Row = LayoutFn((props: RowProps) => rowMeasurePolicy(props));
Row.displayName = 'Row';
