import type { SceneTokensSessionEvent, SceneTokensSessionState } from '../../shared/types';

function emptyState(): SceneTokensSessionState {
  return {
    revision: 1,
    byPlacementId: {},
  };
}

export class SceneTokensSessionStore {
  private state: SceneTokensSessionState = emptyState();

  getState(): SceneTokensSessionState {
    return this.state;
  }

  reset(): SceneTokensSessionState {
    if (Object.keys(this.state.byPlacementId).length === 0) return this.state;
    this.state = {
      revision: this.state.revision + 1,
      byPlacementId: {},
    };
    return this.state;
  }

  dispatch(event: SceneTokensSessionEvent): SceneTokensSessionState {
    switch (event.kind) {
      case 'clear':
        return this.reset();
      case 'move': {
        const placementId = String(event.placementId ?? '');
        if (!placementId) return this.state;
        const nx = Math.max(0, Math.min(1, event.nx));
        const ny = Math.max(0, Math.min(1, event.ny));
        if (!Number.isFinite(nx) || !Number.isFinite(ny)) return this.state;
        const prev = this.state.byPlacementId[placementId];
        if (prev && prev.nx === nx && prev.ny === ny) return this.state;
        this.state = {
          revision: this.state.revision + 1,
          byPlacementId: {
            ...this.state.byPlacementId,
            [placementId]: { nx, ny },
          },
        };
        return this.state;
      }
      default: {
        const _exhaustive: never = event;
        void _exhaustive;
        return this.state;
      }
    }
  }
}
