// 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.dev: 'last-active-dev-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);
  }
}
