import { isMap, isPair, isScalar } from '../../nodes/identity.mjs';
import { Pair, createPair } from '../../nodes/Pair.mjs';
import { YAMLMap, findPair } from '../../nodes/YAMLMap.mjs';

class YAMLSet extends YAMLMap {
  constructor(schema) {
    super(schema);
    this.tag = YAMLSet.tag;
  }
  add(key) {
    let pair;
    if (isPair(key)) pair = key;else if (key && typeof key === 'object' && 'key' in key && 'value' in key && key.value === null) pair = new Pair(key.key, null);else pair = new Pair(key, null);
    const prev = findPair(this.items, pair.key);
    if (!prev) this.items.push(pair);
  }
  /**
   * If `keepPair` is `true`, returns the Pair matching `key`.
   * Otherwise, returns the value of that Pair's key.
   */
  get(key, keepPair) {
    const pair = findPair(this.items, key);
    return !keepPair && isPair(pair) ? isScalar(pair.key) ? pair.key.value : pair.key : pair;
  }
  set(key, value) {
    if (typeof value !== 'boolean') throw new Error(`Expected boolean value for set(key, value) in a YAML set, not ${typeof value}`);
    const prev = findPair(this.items, key);
    if (prev && !value) {
      this.items.splice(this.items.indexOf(prev), 1);
    } else if (!prev && value) {
      this.items.push(new Pair(key));
    }
  }
  toJSON(_, ctx) {
    return super.toJSON(_, ctx, Set);
  }
  toString(ctx, onComment, onChompKeep) {
    if (!ctx) return JSON.stringify(this);
    if (this.hasAllNullValues(true)) return super.toString(Object.assign({}, ctx, {
      allNullValues: true
    }), onComment, onChompKeep);else throw new Error('Set items must all have null values');
  }
  static from(schema, iterable, ctx) {
    const {
      replacer
    } = ctx;
    const set = new this(schema);
    if (iterable && Symbol.iterator in Object(iterable)) for (let value of iterable) {
      if (typeof replacer === 'function') value = replacer.call(iterable, value, value);
      set.items.push(createPair(value, null, ctx));
    }
    return set;
  }
}
YAMLSet.tag = 'tag:yaml.org,2002:set';
const set = {
  collection: 'map',
  identify: value => value instanceof Set,
  nodeClass: YAMLSet,
  default: false,
  tag: 'tag:yaml.org,2002:set',
  createNode: (schema, iterable, ctx) => YAMLSet.from(schema, iterable, ctx),
  resolve(map, onError) {
    if (isMap(map)) {
      if (map.hasAllNullValues(true)) return Object.assign(new YAMLSet(), map);else onError('Set items must all have null values');
    } else onError('Expected a mapping for this tag');
    return map;
  }
};

export { YAMLSet, set };
