import {EVENT_SELECT} from './config.js';
import {add, copy, mult} from './vector.js';

export class Select {
  sim = undefined;
  box = {
    start: undefined,
    end: undefined,
  };
  selectedSingle = undefined;
  selectedGroup = [];

  constructor(sim) {
    this.sim = sim;

    // TODO: Move this to a new Keyboard class singleton
    window.addEventListener('keydown', (e) => {
      switch (e.key) {
        case 'Tab': {
          e.preventDefault();
          if (!this.selectedGroup.length) return;
          const currentIdx = this.selectedGroup.indexOf(this.selectedSingle);
          const newIdx = (currentIdx + 1) % this.selectedGroup.length;
          this.selectedSingle = this.selectedGroup[newIdx];
          break;
        }
      }
    });
  }

  handlePointerDown({x: clientX, y: clientY}) {
    this.box.start = this.sim.screenToSim(clientX, clientY);
    this.box.end = this.box.start;
    // this.getSelectedObjects();
  }

  handlePointerMove({x: clientX, y: clientY}) {
    if (!this.box.start) return;
    this.box.end = this.sim.screenToSim(clientX, clientY);
  }

  handlePointerUp() {
    if (!this.box.start) return;
    const start = copy(this.box.start);
    const end = copy(this.box.end);
    this.box.start = {
      x: Math.min(start.x, end.x),
      y: Math.min(start.y, end.y),
    };
    this.box.end = {
      x: Math.max(start.x, end.x),
      y: Math.max(start.y, end.y),
    };
    this.getSelectedObjects();
    this.sim.div.dispatchEvent(new CustomEvent(EVENT_SELECT));
    this.box = {
      start: undefined,
      end: undefined,
    };
  }

  frame(elapsedTime) {
    if (!this.box.start) return;
    // If panning, let's update the position of our box so it doesn't drift away
    const {velocity} = this.sim.panning;
    const delta = mult(velocity, elapsedTime);
    this.box.start = add(this.box.start, delta);
    this.box.end = add(this.box.end, delta);
    // Display the box
    this.sim.display.drawBox(this.box.start, this.box.end);
  }

  getSelectedObjects() {
    const {start, end} = this.box;
    if (!start) return;
    this.selectedGroup = this.sim.system.filter(({position: {x, y}}) => {
      return x >= start.x && x <= end.x && y >= start.y && y <= end.y;
    });
    // For now, first object in group is selected single
    this.selectedSingle = this.selectedGroup[0] ?? undefined;
  }

  // cb: ({selectedGroup, selectedSingle}) => undefined
  onSelect(cb) {
    this.sim.div.addEventListener(EVENT_SELECT, () => {
      const {selectedGroup, selectedSingle} = this;
      cb({selectedGroup, selectedSingle});
    });
  }
}
