import type { Terrain } from "../document/terrains";
import { TERRAIN_LAYER_COUNT } from "../document/terrains";

export type TerrainBrushTool =
  | "raise"
  | "lower"
  | "smooth"
  | "flatten"
  | "paint";

export interface TerrainBrushSettings {
  radius: number;
  strength: number;
  falloff: number;
}

export interface ArmedTerrainSculptBrushState extends TerrainBrushSettings {
  terrainId: string;
  tool: Exclude<TerrainBrushTool, "paint">;
}

export interface ArmedTerrainPaintBrushState extends TerrainBrushSettings {
  terrainId: string;
  tool: "paint";
  layerIndex: number;
}

export type ArmedTerrainBrushState =
  | ArmedTerrainSculptBrushState
  | ArmedTerrainPaintBrushState;

export interface TerrainBrushStrokeCommit {
  terrain: Terrain;
  commandLabel: string;
  tool: TerrainBrushTool;
}

export const DEFAULT_TERRAIN_BRUSH_RADIUS = 2;
export const DEFAULT_TERRAIN_BRUSH_STRENGTH = 0.35;
export const DEFAULT_TERRAIN_BRUSH_FALLOFF = 0.6;
export const MIN_TERRAIN_BRUSH_RADIUS = 0.25;
export const MAX_TERRAIN_BRUSH_RADIUS = 12;
export const MIN_TERRAIN_BRUSH_STRENGTH = 0.05;
export const MAX_TERRAIN_BRUSH_STRENGTH = 1;
export const MIN_TERRAIN_BRUSH_FALLOFF = 0;
export const MAX_TERRAIN_BRUSH_FALLOFF = 1;

function clamp(value: number, min: number, max: number): number {
  return Math.min(max, Math.max(min, value));
}

export function clampTerrainBrushRadius(radius: number): number {
  if (!Number.isFinite(radius)) {
    return DEFAULT_TERRAIN_BRUSH_RADIUS;
  }

  return clamp(radius, MIN_TERRAIN_BRUSH_RADIUS, MAX_TERRAIN_BRUSH_RADIUS);
}

export function clampTerrainBrushStrength(strength: number): number {
  if (!Number.isFinite(strength)) {
    return DEFAULT_TERRAIN_BRUSH_STRENGTH;
  }

  return clamp(
    strength,
    MIN_TERRAIN_BRUSH_STRENGTH,
    MAX_TERRAIN_BRUSH_STRENGTH
  );
}

export function clampTerrainBrushFalloff(falloff: number): number {
  if (!Number.isFinite(falloff)) {
    return DEFAULT_TERRAIN_BRUSH_FALLOFF;
  }

  return clamp(
    falloff,
    MIN_TERRAIN_BRUSH_FALLOFF,
    MAX_TERRAIN_BRUSH_FALLOFF
  );
}

export function createDefaultTerrainBrushSettings(): TerrainBrushSettings {
  return {
    radius: DEFAULT_TERRAIN_BRUSH_RADIUS,
    strength: DEFAULT_TERRAIN_BRUSH_STRENGTH,
    falloff: DEFAULT_TERRAIN_BRUSH_FALLOFF
  };
}

export function clampTerrainPaintLayerIndex(layerIndex: number): number {
  if (!Number.isFinite(layerIndex)) {
    return 0;
  }

  return Math.min(
    TERRAIN_LAYER_COUNT - 1,
    Math.max(0, Math.round(layerIndex))
  );
}

export function getTerrainBrushToolLabel(tool: TerrainBrushTool): string {
  switch (tool) {
    case "raise":
      return "Raise";
    case "lower":
      return "Lower";
    case "smooth":
      return "Smooth";
    case "flatten":
      return "Flatten";
    case "paint":
      return "Paint";
  }
}

export function getTerrainBrushCommandLabel(tool: TerrainBrushTool): string {
  return `${getTerrainBrushToolLabel(tool)} terrain`;
}
