// Copyright (c) 2021, 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:path/path.dart' as path;

import '../exceptions.dart';
import '../io.dart';
import '../log.dart' as log;
import 'credential.dart';

/// Stores and manages authentication credentials.
class TokenStore {
  TokenStore(this.configDir);

  /// Cache directory.
  final String? configDir;

  /// List of saved authentication tokens.
  ///
  /// Modifying this field will not write changes to the disk. You have to call
  /// [flush] to save changes.
  Iterable<Credential> get credentials => _loadCredentials();

  /// Reads "pub-tokens.json" and parses / deserializes it into list of
  /// [Credential].
  List<Credential> _loadCredentials() {
    final result = <Credential>[];
    final path = _tokensFile;
    if (path == null || !fileExists(path)) {
      return result;
    }

    try {
      dynamic json;
      try {
        json = jsonDecode(readTextFile(path));
      } on FormatException {
        throw FormatException('$path is not valid JSON');
      }

      if (json is! Map<String, dynamic>) {
        throw FormatException('JSON contents is corrupted or not supported');
      }
      if (json['version'] != 1) {
        throw FormatException('Version is not supported');
      }

      if (json.containsKey('hosted')) {
        final hosted = json['hosted'];

        if (hosted is! List) {
          throw FormatException('Invalid or not supported format');
        }

        for (final element in hosted) {
          try {
            if (element is! Map<String, dynamic>) {
              throw FormatException('Invalid or not supported format');
            }

            final credential = Credential.fromJson(element);
            result.add(credential);

            if (!credential.isValid()) {
              throw FormatException('Invalid or not supported credential');
            }
          } on FormatException catch (e) {
            if (element['url'] is String) {
              log.warning(
                'Failed to load credentials for ${element['url']}: '
                '${e.message}',
              );
            } else {
              log.warning(
                'Failed to load credentials for unknown hosted repository: '
                '${e.message}',
              );
            }
          }
        }
      }
    } on FormatException catch (e) {
      log.warning('Failed to load pub-tokens.json: ${e.message}');
    }

    return result;
  }

  Never missingConfigDir() {
    final variable = Platform.isWindows ? '%APPDATA%' : r'$HOME';
    throw DataException('No config dir found. Check that $variable is set');
  }

  /// Writes [credentials] into "pub-tokens.json".
  void _saveCredentials(List<Credential> credentials) {
    final tokensFile = _tokensFile;
    if (tokensFile == null) {
      missingConfigDir();
    }
    ensureDir(path.dirname(tokensFile));
    writeTextFile(
      tokensFile,
      jsonEncode(<String, dynamic>{
        'version': 1,
        'hosted': credentials.map((it) => it.toJson()).toList(),
      }),
    );
  }

  /// Adds [token] into store and writes into disk.
  void addCredential(Credential token) {
    final credentials = _loadCredentials();

    // Remove duplicate tokens
    credentials.removeWhere((it) => it.url == token.url);
    credentials.add(token);
    _saveCredentials(credentials);
  }

  /// Removes tokens with matching [hostedUrl] from store. Returns whether or
  /// not there's a stored token with matching url.
  bool removeCredential(Uri hostedUrl) {
    final credentials = _loadCredentials();

    var i = 0;
    var found = false;
    while (i < credentials.length) {
      if (credentials[i].url == hostedUrl) {
        credentials.removeAt(i);
        found = true;
      } else {
        i++;
      }
    }

    _saveCredentials(credentials);

    return found;
  }

  /// Returns [Credential] for authenticating given [hostedUrl] or `null` if no
  /// matching credential is found.
  Credential? findCredential(Uri hostedUrl) {
    Credential? matchedCredential;
    for (final credential in credentials) {
      if (credential.url == hostedUrl && credential.isValid()) {
        if (matchedCredential == null) {
          matchedCredential = credential;
        } else {
          log.warning(
            'Found multiple matching authentication tokens for "$hostedUrl". '
            'First matching token will be used for authentication.',
          );
          break;
        }
      }
    }

    return matchedCredential;
  }

  /// Returns whether or not store contains a token that could be used for
  /// authenticating given [url].
  bool hasCredential(Uri url) {
    return credentials.any((it) => it.url == url && it.isValid());
  }

  /// Deletes pub-tokens.json file from the disk.
  void deleteTokensFile() {
    final tokensFile = _tokensFile;
    if (tokensFile == null) {
      missingConfigDir();
    } else if (!fileExists(tokensFile)) {
      log.message('No credentials file found at "$tokensFile"');
    } else {
      deleteEntry(tokensFile);
      log.message('pub-tokens.json is deleted.');
    }
  }

  /// Full path to the "pub-tokens.json" file.
  ///
  /// `null` if no config directory could be found.
  String? get _tokensFile {
    var dir = configDir;
    return dir == null ? null : path.join(dir, 'pub-tokens.json');
  }
}
