import { IWT2_BOSS_METADATA, type Iwt2BossId } from '../content/bosses'
import { IWT2_CLASS_METADATA } from '../content/classes'
import {
  createInitialIwt2ArenaState as createCoreIwt2ArenaState,
  tickIwt2Arena as tickCoreIwt2Arena,
} from './arena'
import type {
  Iwt2ArenaIndicator,
  Iwt2ArenaInput,
  Iwt2ArenaState as Iwt2CoreArenaState,
  Iwt2BossEntityState,
  Iwt2HostileAddState,
  Iwt2PartyEntityState,
} from './types'

export type Iwt2ArenaEntityKind = 'player' | 'party' | 'boss' | 'projectile' | 'hostileAdd'

export type Iwt2ArenaEntity = {
  id: string
  kind: Iwt2ArenaEntityKind
  icon: string
  color: string
  x: number
  y: number
  radius: number
  health: number
  maxHealth: number
  stunnedFor: number
}

export type Iwt2ArenaTelegraph =
  | {
    kind: 'charge'
    x: number
    y: number
    width: number
    height: number
    active: boolean
  }
  | {
    kind: 'slam'
    x: number
    y: number
    radius: number
    active: boolean
  }

export type Iwt2ArenaState = Iwt2CoreArenaState & {
  arena: {
    width: number
    height: number
  }
  entities: Iwt2ArenaEntity[]
  telegraphs: Iwt2ArenaTelegraph[]
}

export function createInitialIwt2ArenaState(bossId?: Iwt2BossId, bossIds?: Iwt2BossId[]): Iwt2ArenaState {
  return decorateArenaState(createCoreIwt2ArenaState(bossId, bossIds))
}

export function tickIwt2Arena(state: Iwt2ArenaState, input: Iwt2ArenaInput, dt: number): Iwt2ArenaState {
  return decorateArenaState(tickCoreIwt2Arena(state, input, dt))
}

export function decorateArenaState(state: Iwt2CoreArenaState): Iwt2ArenaState {
  return {
    ...state,
    arena: { ...state.bounds },
    entities: [
      ...state.party.map(toArenaEntity),
      ...state.hostileAdds.map(toHostileAddArenaEntity),
      ...state.bosses.map(toBossArenaEntity),
    ],
    telegraphs: createTelegraphs(state.indicators),
  }
}

function toHostileAddArenaEntity(add: Iwt2HostileAddState): Iwt2ArenaEntity {
  return {
    id: add.id,
    kind: 'hostileAdd',
    icon: 'v',
    color: '#f0b84f',
    x: add.position.x,
    y: add.position.y,
    radius: add.radius,
    health: add.health,
    maxHealth: add.maxHealth,
    stunnedFor: 0,
  }
}

function toArenaEntity(member: Iwt2PartyEntityState): Iwt2ArenaEntity {
  const metadata = IWT2_CLASS_METADATA[member.classId]
  return {
    id: member.id,
    kind: member.aiRole === 'player' ? 'player' : 'party',
    icon: metadata.icon,
    color: metadata.color,
    x: member.position.x,
    y: member.position.y,
    radius: member.radius,
    health: member.health,
    maxHealth: member.maxHealth,
    stunnedFor: Math.max(member.status.stunnedSeconds, member.status.knockedDownSeconds),
  }
}

function toBossArenaEntity(boss: Iwt2BossEntityState): Iwt2ArenaEntity {
  const metadata = IWT2_BOSS_METADATA[boss.bossId]
  return {
    id: boss.id,
    kind: 'boss',
    icon: metadata.icon,
    color: metadata.color,
    x: boss.position.x,
    y: boss.position.y,
    radius: boss.radius,
    health: boss.health,
    maxHealth: boss.maxHealth,
    stunnedFor: 0,
  }
}

function createTelegraphs(indicators: Iwt2ArenaIndicator[]): Iwt2ArenaTelegraph[] {
  return indicators.flatMap((indicator): Iwt2ArenaTelegraph[] => {
    if (indicator.kind === 'lane') {
      return [{
        active: indicator.phase === 'active',
        height: indicator.width * 2,
        kind: 'charge' as const,
        width: Math.max(16, Math.hypot(indicator.end.x - indicator.start.x, indicator.end.y - indicator.start.y)),
        x: Math.min(indicator.start.x, indicator.end.x),
        y: Math.min(indicator.start.y, indicator.end.y) - indicator.width,
      }]
    }
    if (indicator.kind === 'circle') {
      return [{
        active: indicator.phase === 'active',
        kind: 'slam' as const,
        radius: indicator.radius,
        x: indicator.position.x,
        y: indicator.position.y,
      }]
    }
    return []
  })
}
