import { eventBus } from '../lib/eventBus.js';
import { saveState } from './SaveState.js';

class ProgressionSystem {
  constructor() {
    this._access = new Set();
    this._vms = new Set();
    this._docs = new Set();
  }

  initialize(state) {
    const progression = state.progression ?? {};
    this._access = new Set(progression.unlocked_access ?? []);
    this._vms = new Set(progression.unlocked_vms ?? []);
    this._docs = new Set(progression.unlocked_docs ?? []);
  }

  grantUnlock(unlock) {
    let changed = false;

    changed = this._addAll(this._access, unlock.grants_access) || changed;
    changed = this._addAll(this._vms, unlock.grants_vms) || changed;
    changed = this._addAll(this._docs, unlock.grants_docs) || changed;

    if (changed) {
      this._persist();
      eventBus.emit('progression:changed', this._snapshot());
    }
  }

  revokeUnlock(unlock) {
    let changed = false;

    changed = this._removeAll(this._access, unlock.revokes) || changed;
    changed = this._removeAll(this._vms, unlock.revokes_vms) || changed;

    if (changed) {
      this._persist();
      eventBus.emit('progression:changed', this._snapshot());
    }
  }

  hasDoc(id) {
    return this._docs.has(id);
  }

  hasVM(id) {
    return this._vms.has(id);
  }

  hasAccess(key) {
    return this._access.has(key);
  }

  getAccessLevel() {
    if (
      this._access.has('sudo:workstation:full') ||
      this._access.has('sudo:web_server:full') ||
      this._access.has('sudo:build_machine:full')
    ) {
      return 'root';
    }
    if (
      this._access.has('sudo:workstation:systemctl') ||
      this._access.has('ssh:web_server') ||
      this._access.has('ssh:build_machine')
    ) {
      return 'sudo';
    }
    return 'basic_user';
  }

  _snapshot() {
    return {
      unlockedDocs: [...this._docs],
      unlockedVMs: [...this._vms],
      unlockedAccess: [...this._access]
    };
  }

  _persist() {
    saveState.set({
      progression: {
        unlocked_access: [...this._access],
        unlocked_vms: [...this._vms],
        unlocked_docs: [...this._docs]
      }
    });
  }

  _addAll(target, values = []) {
    let changed = false;
    for (const value of values) {
      if (!target.has(value)) {
        target.add(value);
        changed = true;
      }
    }
    return changed;
  }

  _removeAll(target, values = []) {
    let changed = false;
    for (const value of values) {
      if (target.delete(value)) {
        changed = true;
      }
    }
    return changed;
  }
}

export const progressionSystem = new ProgressionSystem();
