import { type RemoteMapConfig } from '../../utils/remoteMapConfig'
import { type GameAudioConfig } from '../audio/audioConfig'
import { type GameHapticsConfig, type GameUiEffectsConfig } from '../feedback/feedbackConfig'
import { getGameModeDefaults } from './gameModeDefaults'
import {
  resolveSystemSettingsState,
  type ResolvedSystemSettingsState,
} from './systemSettingsState'
import { type CourseStyleConfig } from '../presentation/courseStyleConfig'
import { type GpsMarkerStyleConfig } from '../presentation/gpsMarkerStyleConfig'
import { type TrackVisualizationConfig } from '../presentation/trackStyleConfig'
import { mergeTelemetrySources, type PlayerTelemetryProfile } from '../telemetry/playerTelemetryProfile'
import { type TelemetryConfig } from '../telemetry/telemetryConfig'

export interface RuntimeMapProfile {
  title: string
  tileSource: string
  projectionModeText: string
  magneticDeclinationText: string
  cpRadiusMeters: number
  projection: string
  magneticDeclinationDeg: number
  minZoom: number
  maxZoom: number
  initialZoom: number
  initialCenterTileX: number
  initialCenterTileY: number
  tileBoundsByZoom: RemoteMapConfig['tileBoundsByZoom']
  courseStatusText: string
}

export interface RuntimeGameProfile {
  mode: RemoteMapConfig['gameMode']
  sessionCloseAfterMs: number
  sessionCloseWarningMs: number
  minCompletedControlsBeforeFinish: number
  punchPolicy: RemoteMapConfig['punchPolicy']
  punchRadiusMeters: number
  requiresFocusSelection: boolean
  skipEnabled: boolean
  skipRadiusMeters: number
  skipRequiresConfirm: boolean
  autoFinishOnLastControl: boolean
  defaultControlScore: number | null
}

export interface RuntimePresentationProfile {
  course: CourseStyleConfig
  track: TrackVisualizationConfig
  gpsMarker: GpsMarkerStyleConfig
}

export interface RuntimeFeedbackProfile {
  audio: GameAudioConfig
  haptics: GameHapticsConfig
  uiEffects: GameUiEffectsConfig
}

export interface RuntimeTelemetryProfile {
  config: TelemetryConfig
  playerProfile: PlayerTelemetryProfile | null
}

export interface RuntimeSettingsProfile extends ResolvedSystemSettingsState {
  lockLifetimeActive: boolean
}

export interface CompiledRuntimeProfile {
  map: RuntimeMapProfile
  game: RuntimeGameProfile
  settings: RuntimeSettingsProfile
  telemetry: RuntimeTelemetryProfile
  presentation: RuntimePresentationProfile
  feedback: RuntimeFeedbackProfile
}

export interface CompileRuntimeProfileOptions {
  playerTelemetryProfile?: PlayerTelemetryProfile | null
  settingsLockLifetimeActive?: boolean
  storedSettingsKey?: string
}

export function compileRuntimeProfile(
  config: RemoteMapConfig,
  options?: CompileRuntimeProfileOptions,
): CompiledRuntimeProfile {
  const modeDefaults = getGameModeDefaults(config.gameMode)
  const lockLifetimeActive = !!(options && options.settingsLockLifetimeActive === true)
  const playerTelemetryProfile = options && options.playerTelemetryProfile
    ? Object.assign({}, options.playerTelemetryProfile)
    : null

  const settings = resolveSystemSettingsState(
    config.systemSettingsConfig,
    options && options.storedSettingsKey ? options.storedSettingsKey : undefined,
    lockLifetimeActive,
  )

  return {
    map: {
      title: config.configTitle,
      tileSource: config.tileSource,
      projectionModeText: config.projectionModeText,
      magneticDeclinationText: config.magneticDeclinationText,
      cpRadiusMeters: config.cpRadiusMeters,
      projection: config.projection,
      magneticDeclinationDeg: config.magneticDeclinationDeg,
      minZoom: config.minZoom,
      maxZoom: config.maxZoom,
      initialZoom: config.defaultZoom,
      initialCenterTileX: config.initialCenterTileX,
      initialCenterTileY: config.initialCenterTileY,
      tileBoundsByZoom: config.tileBoundsByZoom,
      courseStatusText: config.courseStatusText,
    },
    game: {
      mode: config.gameMode,
      sessionCloseAfterMs: config.sessionCloseAfterMs || modeDefaults.sessionCloseAfterMs,
      sessionCloseWarningMs: config.sessionCloseWarningMs || modeDefaults.sessionCloseWarningMs,
      minCompletedControlsBeforeFinish: config.minCompletedControlsBeforeFinish,
      punchPolicy: config.punchPolicy,
      punchRadiusMeters: config.punchRadiusMeters,
      requiresFocusSelection: config.requiresFocusSelection,
      skipEnabled: config.skipEnabled,
      skipRadiusMeters: config.skipRadiusMeters,
      skipRequiresConfirm: config.skipRequiresConfirm,
      autoFinishOnLastControl: config.autoFinishOnLastControl,
      defaultControlScore: config.defaultControlScore,
    },
    settings: {
      values: settings.values,
      locks: settings.locks,
      lockLifetimeActive,
    },
    telemetry: {
      config: mergeTelemetrySources(config.telemetryConfig, playerTelemetryProfile),
      playerProfile: playerTelemetryProfile,
    },
    presentation: {
      course: config.courseStyleConfig,
      track: config.trackStyleConfig,
      gpsMarker: config.gpsMarkerStyleConfig,
    },
    feedback: {
      audio: config.audioConfig,
      haptics: config.hapticsConfig,
      uiEffects: config.uiEffectsConfig,
    },
  }
}
