import type { DocumentSnapshot } from './types'

export type BodyFeatureState = {
  id: string
  typeId: string
  suppressed: boolean
  upstreamSuppressed: boolean
  solid: boolean
}

const nonSolidBodyTypeIds = new Set([
  'Sketcher::SketchObject',
  'PartDesign::Body',
  'PartDesign::Plane',
  'PartDesign::Line',
  'PartDesign::Point',
  'PartDesign::ShapeBinder',
  'PartDesign::SubShapeBinder',
])

export const resolveBodyTip = (features: readonly BodyFeatureState[]): string | null => {
  for (let index = features.length - 1; index >= 0; index -= 1) {
    const feature = features[index]
    if (feature.solid && !feature.suppressed && !feature.upstreamSuppressed) return feature.id
  }
  return null
}

export const redirectBodyTips = (document: DocumentSnapshot, objectStates: Record<string, string>): string[] => {
  const changed: string[] = []
  for (const bodyItem of document.tree.filter((item) => item.type === 'body')) {
    const body = document.objects.find((object) => object.id === bodyItem.id)
    const tip = body?.properties.find((property) => property.name === 'Tip')
    if (!body || !tip) continue
    const features = (bodyItem.children ?? []).map((id) => {
      const object = document.objects.find((candidate) => candidate.id === id)
      return {
        id,
        typeId: object?.typeId ?? '',
        suppressed: objectStates[id] === 'suppressed',
        upstreamSuppressed: objectStates[id] === 'upstream-suppressed',
        solid: Boolean(object && !nonSolidBodyTypeIds.has(object.typeId)),
      }
    })
    const nextTip = resolveBodyTip(features)
    if (tip.value !== nextTip) {
      tip.value = nextTip
      changed.push(body.id)
    }
  }
  return changed
}
