// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:meta/meta.dart';

import 'base/config.dart';
import 'base/context.dart';
import 'base/file_system.dart';
import 'base/logger.dart';
import 'base/platform.dart';
import 'version.dart';

/// A class that represents global (non-project-specific) internal state that
/// must persist across tool invocations.
abstract class PersistentToolState {
  factory PersistentToolState({
    required FileSystem fileSystem,
    required Logger logger,
    required Platform platform,
  }) => _DefaultPersistentToolState(
    fileSystem: fileSystem,
    logger: logger,
    platform: platform,
  );

  factory PersistentToolState.test({
    required Directory directory,
    required Logger logger,
  }) => _DefaultPersistentToolState.test(
    directory: directory,
    logger: logger,
  );

  static PersistentToolState? get instance => context.get<PersistentToolState>();

  /// Whether the welcome message should be redisplayed.
  ///
  /// May give null if the value has not been set.
  bool? get shouldRedisplayWelcomeMessage;
  void setShouldRedisplayWelcomeMessage(bool value); // Enforced nonnull setter.

  /// Returns the last active version for a given [channel].
  ///
  /// If there was no active prior version, returns `null` instead.
  String? lastActiveVersion(Channel channel);

  /// Update the last active version for a given [channel].
  void updateLastActiveVersion(String fullGitHash, Channel channel);

  /// Return the hash of the last active license terms.
  String? get lastActiveLicenseTermsHash;
  void setLastActiveLicenseTermsHash(String value); // Enforced nonnull setter.

  /// Whether this client was already determined to be or not be a bot.
  bool? get isRunningOnBot;
  void setIsRunningOnBot(bool value); // Enforced nonnull setter.
}

class _DefaultPersistentToolState implements PersistentToolState {
  _DefaultPersistentToolState({
    required FileSystem fileSystem,
    required Logger logger,
    required Platform platform,
  }) : _config = Config(
      _kFileName,
      fileSystem: fileSystem,
      logger: logger,
      platform: platform,
    );

  @visibleForTesting
  _DefaultPersistentToolState.test({
    required Directory directory,
    required Logger logger,
  }) : _config = Config.test(
      name: _kFileName,
      directory: directory,
      logger: logger,
    );

  static const String _kFileName = 'tool_state';
  static const String _kRedisplayWelcomeMessage = 'redisplay-welcome-message';
  static const Map<Channel, String> _lastActiveVersionKeys = <Channel,String>{
    Channel.master: 'last-active-master-version',
    Channel.beta: 'last-active-beta-version',
    Channel.stable: 'last-active-stable-version',
  };
  static const String _kBotKey = 'is-bot';
  static const String _kLicenseHash = 'license-hash';

  final Config _config;

  @override
  bool? get shouldRedisplayWelcomeMessage {
    return _config.getValue(_kRedisplayWelcomeMessage) as bool?;
  }

  @override
  void setShouldRedisplayWelcomeMessage(bool value) {
    _config.setValue(_kRedisplayWelcomeMessage, value);
  }

  @override
  String? lastActiveVersion(Channel channel) {
    final String? versionKey = _versionKeyFor(channel);
    assert(versionKey != null);
    return _config.getValue(versionKey!) as String?;
  }

  @override
  void updateLastActiveVersion(String fullGitHash, Channel channel) {
    final String? versionKey = _versionKeyFor(channel);
    assert(versionKey != null);
    _config.setValue(versionKey!, fullGitHash);
  }

  @override
  String? get lastActiveLicenseTermsHash => _config.getValue(_kLicenseHash) as String?;

  @override
  void setLastActiveLicenseTermsHash(String value) {
    _config.setValue(_kLicenseHash, value);
  }

  String? _versionKeyFor(Channel channel) {
    return _lastActiveVersionKeys[channel];
  }

  @override
  bool? get isRunningOnBot => _config.getValue(_kBotKey) as bool?;

  @override
  void setIsRunningOnBot(bool value) {
    _config.setValue(_kBotKey, value);
  }
}
