// Copyright (c) 2014, 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 'context.dart';
import 'style.dart';

/// The internal interface for the [Style] type.
///
/// Users should be able to pass around instances of [Style] like an enum, but
/// the members that [Context] uses should be hidden from them. Those members
/// are defined on this class instead.
abstract class InternalStyle extends Style {
  /// The default path separator for this style.
  ///
  /// On POSIX, this is `/`. On Windows, it's `\`.
  String get separator;

  /// Returns whether [path] contains a separator.
  bool containsSeparator(String path);

  /// Returns whether [codeUnit] is the character code of a separator.
  bool isSeparator(int codeUnit);

  /// Returns whether this path component needs a separator after it.
  ///
  /// Windows and POSIX styles just need separators when the previous component
  /// doesn't already end in a separator, but the URL always needs to place a
  /// separator between the root and the first component, even if the root
  /// already ends in a separator character. For example, to join "file://" and
  /// "usr", an additional "/" is needed (making "file:///usr").
  bool needsSeparator(String path);

  /// Returns the number of characters of the root part.
  ///
  /// Returns 0 if the path is relative and 1 if the path is root-relative.
  ///
  /// If [withDrive] is `true`, this should include the drive letter for `file:`
  /// URLs. Non-URL styles may ignore the parameter.
  int rootLength(String path, {bool withDrive = false});

  /// Gets the root prefix of [path] if path is absolute. If [path] is relative,
  /// returns `null`.
  String getRoot(String path) {
    var length = rootLength(path);
    if (length > 0) return path.substring(0, length);
    return isRootRelative(path) ? path[0] : null;
  }

  /// Returns whether [path] is root-relative.
  ///
  /// If [path] is relative or absolute and not root-relative, returns `false`.
  bool isRootRelative(String path);

  /// Returns the path represented by [uri] in this style.
  String pathFromUri(Uri uri);

  /// Returns the URI that represents the relative path made of [parts].
  Uri relativePathToUri(String path) {
    var segments = context.split(path);

    // Ensure that a trailing slash in the path produces a trailing slash in the
    // URL.
    if (isSeparator(path.codeUnitAt(path.length - 1))) segments.add('');
    return Uri(pathSegments: segments);
  }

  /// Returns the URI that represents [path], which is assumed to be absolute.
  Uri absolutePathToUri(String path);

  /// Returns whether [codeUnit1] and [codeUnit2] are considered equivalent for
  /// this style.
  bool codeUnitsEqual(int codeUnit1, int codeUnit2) => codeUnit1 == codeUnit2;

  /// Returns whether [path1] and [path2] are equivalent.
  ///
  /// This only needs to handle character-by-character comparison; it can assume
  /// the paths are normalized and contain no `..` components.
  bool pathsEqual(String path1, String path2) => path1 == path2;

  int canonicalizeCodeUnit(int codeUnit) => codeUnit;

  String canonicalizePart(String part) => part;
}
