/**
 * @license
 * Copyright 2017 The Bazel Authors. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import * as fs from 'fs';
import * as ts from 'typescript';
import * as perfTrace from './perf_trace';

type Debug = (...msg: Array<{}>) => void;

interface CacheStats {
  reads: number;
  hits: number;
  evictions: number;
}

/**
 * Cache exposes a trivial LRU cache.
 *
 * This code uses the fact that JavaScript hash maps are linked lists - after
 * reaching the cache size limit, it deletes the oldest (first) entries. Used
 * cache entries are moved to the end of the list by deleting and re-inserting.
 */
class Cache<T> {
  private map = new Map<string, T>();
  private stats: CacheStats = {reads: 0, hits: 0, evictions: 0};

  constructor(private name: string, private debug: Debug) {}

  set(key: string, value: T) {
    this.map.set(key, value);
  }

  get(key: string, updateCache = true): T|undefined {
    this.stats.reads++;

    const entry = this.map.get(key);
    if (updateCache) {
      if (entry) {
        this.debug(this.name, 'cache hit:', key);
        this.stats.hits++;
        // Move an entry to the end of the cache by deleting and re-inserting
        // it.
        this.map.delete(key);
        this.map.set(key, entry);
      } else {
        this.debug(this.name, 'cache miss:', key);
      }
      this.traceStats();
    }
    return entry;
  }

  delete(key: string) {
    this.map.delete(key);
  }

  evict(unevictableKeys?: {has: (key: string) => boolean}): number {
    // Drop half the cache, the least recently used entry == the first entry.
    this.debug('Evicting from the', this.name, 'cache...');
    const originalSize = this.map.size;
    let numberKeysToDrop = originalSize / 2;
    if (numberKeysToDrop === 0) {
      return 0;
    }
    // Map keys are iterated in insertion order, since we reinsert on access
    // this is indeed a LRU strategy.
    // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map/keys
    for (const key of this.map.keys()) {
      if (numberKeysToDrop === 0) break;
      if (unevictableKeys && unevictableKeys.has(key)) continue;
      this.map.delete(key);
      numberKeysToDrop--;
    }
    const keysDropped = originalSize - this.map.size;
    this.stats.evictions += keysDropped;
    this.debug('Evicted', keysDropped, this.name, 'cache entries');
    this.traceStats();
    return keysDropped;
  }

  keys() {
    return this.map.keys();
  }

  resetStats() {
    this.stats = {hits: 0, reads: 0, evictions: 0};
  }

  printStats() {
    let percentage;
    if (this.stats.reads === 0) {
      percentage = 100.00;  // avoid "NaN %"
    } else {
      percentage = (this.stats.hits / this.stats.reads * 100).toFixed(2);
    }
    this.debug(`${this.name} cache stats: ${percentage}% hits`, this.stats);
  }

  traceStats() {
    // counters are rendered as stacked bar charts, so record cache
    // hits/misses rather than the 'reads' stat tracked in stats
    // so the chart makes sense.
    perfTrace.counter(`${this.name} cache hit rate`, {
      'hits': this.stats.hits,
      'misses': this.stats.reads - this.stats.hits,
    });
    perfTrace.counter(`${this.name} cache evictions`, {
      'evictions': this.stats.evictions,
    });
    perfTrace.counter(`${this.name} cache size`, {
      [`${this.name}s`]: this.map.size,
    });
  }
}

interface SourceFileEntry {
  digest: string;  // blaze's opaque digest of the file
  value: ts.SourceFile;
}

/**
 * Default memory size, beyond which we evict from the cache.
 */
const DEFAULT_MAX_MEM_USAGE = 1024 * (1 << 20 /* 1 MB */);

/**
 * FileCache is a trivial LRU cache for bazel outputs.
 *
 * Cache entries are keyed off by an opaque, bazel-supplied digest.
 */
// TODO(martinprobst): Drop the <T> parameter, it's no longer used.
export class FileCache<T = {}> {
  private fileCache = new Cache<SourceFileEntry>('file', this.debug);
  /**
   * FileCache does not know how to construct bazel's opaque digests. This
   * field caches the last (or current) compile run's digests, so that code
   * below knows what digest to assign to a newly loaded file.
   */
  private lastDigests = new Map<string, string>();
  /**
   * FileCache can enter a degenerate state, where all cache entries are pinned
   * by lastDigests, but the system is still out of memory. In that case, do not
   * attempt to free memory until lastDigests has changed.
   */
  private cannotEvict = false;

  /**
   * Because we cannot measuse the cache memory footprint directly, we evict
   * when the process' total memory usage goes beyond this number.
   */
  private maxMemoryUsage = DEFAULT_MAX_MEM_USAGE;

  constructor(private debug: (...msg: Array<{}>) => void) {}

  setMaxCacheSize(maxCacheSize: number) {
    if (maxCacheSize < 0) {
      throw new Error(`FileCache max size is negative: ${maxCacheSize}`);
    }
    this.debug('FileCache max size is', maxCacheSize >> 20, 'MB');
    this.maxMemoryUsage = maxCacheSize;
    this.maybeFreeMemory();
  }

  resetMaxCacheSize() {
    this.setMaxCacheSize(DEFAULT_MAX_MEM_USAGE);
  }

  /**
   * Updates the cache with the given digests.
   *
   * updateCache must be called before loading files - only files that were
   * updated (with a digest) previously can be loaded.
   */
  updateCache(digests: {[k: string]: string}): void;
  updateCache(digests: Map<string, string>): void;
  updateCache(digests: Map<string, string>|{[k: string]: string}) {
    // TODO(martinprobst): drop the Object based version, it's just here for
    // backwards compatibility.
    if (!(digests instanceof Map)) {
      digests = new Map(Object.keys(digests).map(
          (k): [string, string] => [k, (digests as {[k: string]: string})[k]]));
    }
    this.debug('updating digests:', digests);
    this.lastDigests = digests;
    this.cannotEvict = false;
    for (const [filePath, newDigest] of digests.entries()) {
      const entry = this.fileCache.get(filePath, /*updateCache=*/ false);
      if (entry && entry.digest !== newDigest) {
        this.debug(
            'dropping file cache entry for', filePath, 'digests', entry.digest,
            newDigest);
        this.fileCache.delete(filePath);
      }
    }
  }

  getLastDigest(filePath: string): string {
    const digest = this.lastDigests.get(filePath);
    if (!digest) {
      throw new Error(
          `missing input digest for ${filePath}.` +
          `(only have ${Array.from(this.lastDigests.keys())})`);
    }
    return digest;
  }

  getCache(filePath: string): ts.SourceFile|undefined {
    const entry = this.fileCache.get(filePath);
    if (entry) return entry.value;
    return undefined;
  }

  putCache(filePath: string, entry: SourceFileEntry): void {
    const dropped = this.maybeFreeMemory();
    this.fileCache.set(filePath, entry);
    this.debug('Loaded', filePath, 'dropped', dropped, 'file cache entries');
  }

  /**
   * Returns true if the given filePath was reported as an input up front and
   * has a known cache digest. FileCache can only cache known files.
   */
  isKnownInput(filePath: string): boolean {
    return this.lastDigests.has(filePath);
  }

  inCache(filePath: string): boolean {
    return !!this.getCache(filePath);
  }

  resetStats() {
    this.fileCache.resetStats();
  }

  printStats() {
    this.fileCache.printStats();
  }

  traceStats() {
    this.fileCache.traceStats();
  }

  /**
   * Returns whether the cache should free some memory.
   *
   * Defined as a property so it can be overridden in tests.
   */
  shouldFreeMemory: () => boolean = () => {
    return process.memoryUsage().heapUsed > this.maxMemoryUsage;
  };

  /**
   * Frees memory if required. Returns the number of dropped entries.
   */
  maybeFreeMemory() {
    if (!this.shouldFreeMemory() || this.cannotEvict) {
      return 0;
    }
    const dropped = this.fileCache.evict(this.lastDigests);
    if (dropped === 0) {
      // Freeing memory did not drop any cache entries, because all are pinned.
      // Stop evicting until the pinned list changes again. This prevents
      // degenerating into an O(n^2) situation where each file load iterates
      // through the list of all files, trying to evict cache keys in vain
      // because all are pinned.
      this.cannotEvict = true;
    }
    return dropped;
  }

  getCacheKeysForTest() {
    return Array.from(this.fileCache.keys());
  }
}

export interface FileLoader {
  loadFile(fileName: string, filePath: string, langVer: ts.ScriptTarget):
      ts.SourceFile;
  fileExists(filePath: string): boolean;
}

/**
 * Load a source file from disk, or possibly return a cached version.
 */
export class CachedFileLoader implements FileLoader {
  /** Total amount of time spent loading files, for the perf trace. */
  private totalReadTimeMs = 0;

  // TODO(alexeagle): remove unused param after usages updated:
  // angular:packages/bazel/src/ngc-wrapped/index.ts
  constructor(private readonly cache: FileCache, unused?: boolean) {}

  fileExists(filePath: string) {
    return this.cache.isKnownInput(filePath);
  }

  loadFile(fileName: string, filePath: string, langVer: ts.ScriptTarget):
      ts.SourceFile {
    let sourceFile = this.cache.getCache(filePath);
    if (!sourceFile) {
      const readStart = Date.now();
      const sourceText = fs.readFileSync(filePath, 'utf8');
      sourceFile = ts.createSourceFile(fileName, sourceText, langVer, true);
      const entry = {
        digest: this.cache.getLastDigest(filePath),
        value: sourceFile
      };
      const readEnd = Date.now();
      this.cache.putCache(filePath, entry);

      this.totalReadTimeMs += readEnd - readStart;
      perfTrace.counter('file load time', {
        'read': this.totalReadTimeMs,
      });
      perfTrace.snapshotMemoryUsage();
    }

    return sourceFile;
  }
}

/** Load a source file from disk. */
export class UncachedFileLoader implements FileLoader {
  fileExists(filePath: string): boolean {
    return ts.sys.fileExists(filePath);
  }

  loadFile(fileName: string, filePath: string, langVer: ts.ScriptTarget):
      ts.SourceFile {
    const sourceText = fs.readFileSync(filePath, 'utf8');
    return ts.createSourceFile(fileName, sourceText, langVer, true);
  }
}
