import {
  clampSceneViewCamera,
  DEFAULT_SCENE_VIEW_CAMERA,
  type SceneViewCamera,
  type SceneViewEvent,
  type SceneViewState,
} from '../../shared/types';

function emptyState(): SceneViewState {
  return {
    revision: 1,
    ...DEFAULT_SCENE_VIEW_CAMERA,
  };
}

export class SceneViewStore {
  private state: SceneViewState = emptyState();

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

  reset(): SceneViewState {
    if (
      this.state.scale === 1 &&
      this.state.ox === 0.5 &&
      this.state.oy === 0.5
    ) {
      return this.state;
    }
    this.state = {
      revision: this.state.revision + 1,
      ...DEFAULT_SCENE_VIEW_CAMERA,
    };
    return this.state;
  }

  dispatch(event: SceneViewEvent): SceneViewState {
    switch (event.kind) {
      case 'reset':
        return this.reset();
      case 'set': {
        const camera: SceneViewCamera = clampSceneViewCamera(event.camera);
        if (
          camera.scale === this.state.scale &&
          camera.ox === this.state.ox &&
          camera.oy === this.state.oy
        ) {
          return this.state;
        }
        this.state = {
          revision: this.state.revision + 1,
          ...camera,
        };
        return this.state;
      }
      default: {
        const _exhaustive: never = event;
        void _exhaustive;
        return this.state;
      }
    }
  }
}
