//
// Copyright 2020 DXOS.org
//

import { spawnSync } from 'child_process';

class LogCache {
  constructor (maxLines = 500) {
    // Sets in JS iterate in insertion order.
    this.buffer = new Set();
    this.maxLines = maxLines;
  }

  append (lines) {
    const added = [];
    for (const line of lines) {
      if (!this.buffer.has(line)) {
        this.buffer.add(line);
        added.push(line);
      }
    }

    if (this.buffer.size > this.maxLines) {
      this.buffer = new Set(Array.from(this.buffer).slice(parseInt(this.maxLines / 2)));
    }

    return added;
  }
}

const _caches = new Map();

const getLogCache = (name) => {
  let cache = _caches.get(name);
  if (!cache) {
    cache = new LogCache();
    _caches.set(name, cache);
  }
  return cache;
};

const getLogs = async (name, incremental = false, lines = 100) => {
  const command = 'wire';
  const args = ['service', 'logs', '--lines', lines, name];

  const child = spawnSync(command, args, { encoding: 'utf8' });
  const logLines = child.stdout.split(/\n/);
  const cache = getLogCache(name);
  const added = cache.append(logLines);

  return incremental ? added : Array.from(cache.buffer);
};

export const logResolvers = {
  Query: {
    logs: async (_, { service, incremental }) => {
      const lines = await getLogs(service, incremental);
      return {
        timestamp: new Date().toUTCString(),
        json: JSON.stringify({ incremental, lines })
      };
    }
  }
};
