import { is } from './ModelUtil';

import { getParent } from './ModelingUtil';

import { asTRBL } from 'diagram-js/lib/layout/LayoutUtil';

import { substractTRBL, resizeTRBL } from 'diagram-js/lib/features/resize/ResizeUtil';

const abs = Math.abs;

function getTRBLResize(oldBounds: any, newBounds: any) {
  return substractTRBL(asTRBL(newBounds), asTRBL(oldBounds));
}

const LANE_PARENTS = ['bpmn:Participant', 'bpmn:Process', 'bpmn:SubProcess'];

export const LANE_INDENTATION = 30;

export function collectLanes(shape: { children: any[] }, collectedShapes: any[]) {
  collectedShapes = collectedShapes || [];

  shape.children.filter(function (s: any) {
    if (is(s, 'bpmn:Lane')) {
      collectLanes(s, collectedShapes);

      collectedShapes.push(s);
    }
  });

  return collectedShapes;
}

export function getChildLanes(shape: {
  type?: string;
  businessObject?: any;
  id?: any;
  height?: number;
  children?: any;
}) {
  return shape.children.filter(function (c: any) {
    return is(c, 'bpmn:Lane');
  });
}
export function getLanesRoot(shape: any) {
  return getParent(shape, LANE_PARENTS) || shape;
}
export function computeLanesResize(shape: any, newBounds: any) {
  const rootElement = getLanesRoot(shape);

  const initialShapes = is(rootElement, 'bpmn:Process') ? [] : [rootElement];

  const allLanes = collectLanes(rootElement, initialShapes),
    shapeTrbl = asTRBL(shape),
    shapeNewTrbl = asTRBL(newBounds),
    trblResize = getTRBLResize(shape, newBounds),
    resizeNeeded: { shape: any; newBounds: any }[] = [];

  allLanes.forEach(function (other: any) {
    if (other === shape) {
      return;
    }

    let topResize = 0;
    const rightResize = trblResize.right;
    let bottomResize = 0;
    const leftResize = trblResize.left;

    const otherTrbl = asTRBL(other);

    if (trblResize.top) {
      if (abs(otherTrbl.bottom - shapeTrbl.top) < 10) {
        bottomResize = shapeNewTrbl.top - otherTrbl.bottom;
      }

      if (abs(otherTrbl.top - shapeTrbl.top) < 5) {
        topResize = shapeNewTrbl.top - otherTrbl.top;
      }
    }

    if (trblResize.bottom) {
      if (abs(otherTrbl.top - shapeTrbl.bottom) < 10) {
        topResize = shapeNewTrbl.bottom - otherTrbl.top;
      }

      if (abs(otherTrbl.bottom - shapeTrbl.bottom) < 5) {
        bottomResize = shapeNewTrbl.bottom - otherTrbl.bottom;
      }
    }

    if (topResize || rightResize || bottomResize || leftResize) {
      resizeNeeded.push({
        shape: other,
        newBounds: resizeTRBL(other, {
          top: topResize,
          right: rightResize,
          bottom: bottomResize,
          left: leftResize,
        }),
      });
    }
  });

  return resizeNeeded;
}
