import { CondensedGraph } from '../CondensedGraph.js';
import { CondensedGraphIndices } from '../graph/CondensedGraphIndices.js';
import { serializeArbiterSnapshot, deserializeArbiterSnapshot } from '../SnapshotBinary.js';

export class ArbiterSnapshot {
  constructor(arbiter) {
    this.arbiter = arbiter;
  }

  enableCondensedSnapshot(options = {}) {
    const graph = new CondensedGraph(options);
    for (const rel of this.arbiter.relations) {
      const srcKey = this.arbiter.keyByNodeId.get(rel.src);
      const dstKey = this.arbiter.keyByNodeId.get(rel.dst);
      if (!srcKey || !dstKey) continue;
      graph._ensureNodeId(rel.src, srcKey);
      graph._ensureNodeId(rel.dst, dstKey);
      graph.addEdge(rel.src, rel.rel, rel.dst, {
        possibility: rel.possibility,
        reliability: rel.reliability,
        value: rel.value
      });
    }

    if (options.usePerfectHash !== false) {
      graph.finalizePerfectHash();
    }

    if (options.useWaveletAdjacency !== false) {
      graph.finalizeWaveletAdjacency({ dropAdjacencyList: options.dropAdjacencyList !== false });
    }

    this.arbiter.snapshotGraph = graph;
    this.arbiter.indices = new CondensedGraphIndices(graph);
    this.arbiter.indicesBuilt = true;
    this.arbiter.relationManager._relationsChanged = false;
    this.arbiter.snapshotEnabled = true;
    this.arbiter._snapshotReadOnly = true;

    return graph;
  }

  toSnapshotBinary(options = {}) {
    if (!this.arbiter.snapshotGraph) {
      this.enableCondensedSnapshot({
        usePerfectHash: options.usePerfectHash !== false,
        useWaveletAdjacency: options.useWaveletAdjacency !== false,
        dropAdjacencyList: options.dropAdjacencyList !== false
      });
    }

    return serializeArbiterSnapshot(this.arbiter, { graph: this.arbiter.snapshotGraph });
  }

  static fromSnapshotBinary(buffer, options = {}, createArbiter) {
    const arbiter = deserializeArbiterSnapshot(buffer, () => createArbiter(options));
    if (arbiter.snapshotGraph) {
      if (options.buildSnapshotIndices !== false) {
        arbiter.indices = new CondensedGraphIndices(arbiter.snapshotGraph, {
          relationMetadata: arbiter._snapshotRelationMetadata || null
        });
        arbiter.indicesBuilt = true;
      } else {
        arbiter.indicesBuilt = false;
      }
      arbiter.relationManager._relationsChanged = false;
    }
    return arbiter;
  }
}
