// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'dart:convert';
import 'dart:io';

import 'package:meta/meta.dart';
import 'package:path/path.dart';

import 'byte_store.dart';
import 'cache.dart';
import 'file_byte_store.dart';

/// The function that returns current time in milliseconds.
typedef int GetCurrentTime();

/// [ByteStore] that stores values as files, allows to mark some of keys as
/// temporary protected, and supports periodical [flush] of unprotected keys.
///
/// The set of protected keys is stored in a file, which is locked during
/// updating to prevent races across multiple processes.
class ProtectedFileByteStore implements ByteStore {
  @visibleForTesting
  static const PROTECTED_FILE_NAME = '.temporary_protected_keys';

  final String _cachePath;
  final Duration _protectionDuration;
  final GetCurrentTime _getCurrentTimeFunction;

  final FileByteStore _fileByteStore;
  final Cache<String, List<int>> _cache;

  /// Create a new instance of the [ProtectedFileByteStore].
  ///
  /// The [protectionDuration] specifies how long temporary protected keys
  /// stay protected.
  ProtectedFileByteStore(this._cachePath,
      {Duration protectionDuration,
      GetCurrentTime getCurrentTime,
      int cacheSizeBytes: 128 * 1024 * 1024})
      : _protectionDuration = protectionDuration,
        _getCurrentTimeFunction = getCurrentTime ?? _getCurrentTimeDefault,
        _fileByteStore = new FileByteStore(_cachePath),
        _cache = new Cache(cacheSizeBytes, (bytes) => bytes.length);

  /// Remove all not protected keys.
  void flush() {
    var protectedKeysText = _keysReadTextLocked();
    var protectedKeys = new ProtectedKeys.decode(protectedKeysText);
    List<FileSystemEntity> files = new Directory(_cachePath).listSync();
    for (var file in files) {
      if (file is File) {
        String key = basename(file.path);
        if (key == PROTECTED_FILE_NAME) {
          continue;
        }
        if (protectedKeys.containsKey(key)) {
          continue;
        }
        try {
          file.deleteSync();
        } catch (e) {}
      }
    }
  }

  @override
  List<int> get(String key) {
    return _cache.get(key, () => _fileByteStore.get(key));
  }

  @override
  void put(String key, List<int> bytes) {
    if (key == PROTECTED_FILE_NAME) {
      throw new ArgumentError('The key $key is reserved.');
    }
    _fileByteStore.put(key, bytes);
    _cache.put(key, bytes);
  }

  /// The [add] keys are added to the set of temporary protected keys, and
  /// their age is reset to zero.
  ///
  /// The [remove] keys are removed from the set of temporary protected keys,
  /// and become subjects of LRU cached eviction.
  void updateProtectedKeys(
      {List<String> add: const <String>[],
      List<String> remove: const <String>[]}) {
    _withProtectedKeysLockSync(_cachePath, (ProtectedKeys protectedKeys) {
      var now = _getCurrentTimeFunction();

      if (_protectionDuration != null) {
        var maxAge = _protectionDuration.inMilliseconds;
        protectedKeys.removeOlderThan(maxAge, now);
      }

      for (var addedKey in add) {
        protectedKeys.add(addedKey, now);
      }

      for (var removedKey in remove) {
        protectedKeys.remove(removedKey);
      }
    });
  }

  /// Read the protected keys, but don't keep the lock.
  ///
  /// We do this before performing any long running operation that
  /// just read, and where it is important to keep system unlocked.
  String _keysReadTextLocked() {
    File keysFile = new File(join(_cachePath, PROTECTED_FILE_NAME));
    RandomAccessFile keysLock = keysFile.openSync(mode: FileMode.append);
    keysLock.lockSync(FileLock.blockingExclusive);
    try {
      return _keysReadText(keysLock);
    } finally {
      keysLock.unlockSync();
      keysLock.closeSync();
    }
  }

  /// The default implementation of [GetCurrentTime].
  static int _getCurrentTimeDefault() {
    return new DateTime.now().millisecondsSinceEpoch;
  }

  static ProtectedKeys _keysRead(RandomAccessFile file) {
    String text = _keysReadText(file);
    return new ProtectedKeys.decode(text);
  }

  static String _keysReadText(RandomAccessFile file) {
    file.setPositionSync(0);
    List<int> bytes = file.readSync(file.lengthSync());
    return utf8.decode(bytes);
  }

  static void _keysWrite(RandomAccessFile file, ProtectedKeys keys) {
    String text = keys.encode();
    file.setPositionSync(0);
    file.writeStringSync(text);
    file.truncateSync(file.positionSync());
  }

  /// Perform [f] over the locked keys file, decoded into [ProtectedKeys].
  static void _withProtectedKeysLockSync(
      String cachePath, void f(ProtectedKeys keys)) {
    String path = join(cachePath, PROTECTED_FILE_NAME);
    RandomAccessFile file = new File(path).openSync(mode: FileMode.append);
    file.lockSync(FileLock.blockingExclusive);
    try {
      ProtectedKeys keys = _keysRead(file);
      f(keys);
      _keysWrite(file, keys);
    } finally {
      file.unlockSync();
      file.closeSync();
    }
  }
}

/// Container with protected keys.
@visibleForTesting
class ProtectedKeys {
  /// The map from a key in [ByteStore] to the time in milliseconds when the
  /// key was marked as temporary protected.
  final Map<String, int> map;

  ProtectedKeys(this.map);

  factory ProtectedKeys.decode(String text) {
    var map = <String, int>{};
    try {
      List<String> lines = text.split('\n').toList();
      if (lines.length % 2 == 0) {
        for (int i = 0; i < lines.length; i += 2) {
          String key = lines[i];
          String startMillisecondsStr = lines[i + 1];
          int startMilliseconds = int.parse(startMillisecondsStr);
          map[key] = startMilliseconds;
        }
      }
    } catch (e) {}
    return new ProtectedKeys(map);
  }

  /// Add the given [key] with the current time.
  void add(String key, int time) {
    map[key] = time;
  }

  bool containsKey(String key) => map.containsKey(key);

  String encode() {
    var buffer = new StringBuffer();
    map.forEach((key, start) {
      buffer.writeln(key);
      buffer.writeln(start);
    });
    return buffer.toString().trim();
  }

  void remove(String key) {
    map.remove(key);
  }

  /// If the time is [now] milliseconds, remove all keys that are older than
  /// the given [maxAge] is milliseconds.
  void removeOlderThan(int maxAge, int now) {
    var keysToRemove = <String>[];
    for (var key in map.keys) {
      if (now - map[key] > maxAge) {
        keysToRemove.add(key);
      }
    }
    keysToRemove.forEach(map.remove);
  }
}
