// Copyright 2017 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.lib.vfs;

import com.google.devtools.build.lib.util.OS;

/**
 * An interface class representing the differences in path style between different OSs.
 *
 * <p>Eg. case sensitivity, '/' mounts vs. 'C:/', etc.
 */
public interface OsPathPolicy {
  int NORMALIZED = 0; // Path is normalized
  int NEEDS_NORMALIZE = 1; // Path requires normalization

  /** Returns required normalization level, passed to {@link #normalize}. */
  int needsToNormalize(String path);

  /**
   * Returns the required normalization level if an already normalized string is concatenated with
   * another normalized path fragment.
   *
   * <p>This method may be faster than {@link #needsToNormalize(String)}.
   */
  int needsToNormalizeSuffix(String normalizedSuffix);

  /**
   * Normalizes the passed string according to the passed normalization level.
   *
   * @param normalizationLevel The normalizationLevel from {@link #needsToNormalize}
   */
  String normalize(String path, int normalizationLevel);

  /**
   * Returns the length of the mount, eg. 1 for unix '/', 3 for Windows 'C:/'.
   *
   * <p>If the path is relative, 0 is returned
   */
  int getDriveStrLength(String path);

  /** Compares two path strings, using the given OS case sensitivity. */
  int compare(String s1, String s2);

  /** Compares two characters, using the given OS case sensitivity. */
  int compare(char c1, char c2);

  /** Tests two path strings for equality, using the given OS case sensitivity. */
  boolean equals(String s1, String s2);

  /** Computes the hash code for a path string. */
  int hash(String s);

  /**
   * Returns whether the passed string starts with the given prefix, given the OS case sensitivity.
   *
   * <p>This is a pure string operation and doesn't need to worry about matching path segments.
   */
  boolean startsWith(String path, String prefix);

  /**
   * Returns whether the passed string ends with the given prefix, given the OS case sensitivity.
   *
   * <p>This is a pure string operation and doesn't need to worry about matching path segments.
   */
  boolean endsWith(String path, String suffix);

  /** Returns the separator used for normalized paths. */
  char getSeparator();

  /** Returns whether the unnormalized character c is a separator. */
  boolean isSeparator(char c);

  boolean isCaseSensitive();

  static OsPathPolicy getFilePathOs() {
    switch (OS.getCurrent()) {
      case LINUX:
      case FREEBSD:
      case UNKNOWN:
        return UnixOsPathPolicy.INSTANCE;
      case DARWIN:
        // NOTE: We *should* return a path policy that is case insensitive,
        // but we currently don't handle this
        return UnixOsPathPolicy.INSTANCE;
      case WINDOWS:
        return WindowsOsPathPolicy.INSTANCE;
      default:
        throw new AssertionError("Not covering all OSs");
    }
  }

  /** Utilities for implementations of {@link OsPathPolicy}. */
  class Utils {
    /**
     * Normalizes any '.' and '..' in-place in the segment array by shifting other segments to the
     * front. Returns the remaining number of items.
     */
    static int removeRelativePaths(String[] segments, int starti, boolean isAbsolute) {
      int segmentCount = 0;
      int shift = starti;
      int n = segments.length;
      for (int i = starti; i < n; ++i) {
        String segment = segments[i];
        switch (segment) {
          case ".":
            ++shift;
            break;
          case "..":
            if (segmentCount > 0 && !segments[segmentCount - 1].equals("..")) {
              // Remove the last segment, if there is one and it is not "..". This
              // means that the resulting path can still contain ".."
              // segments at the beginning.
              segmentCount--;
              shift += 2;
              break;
            } else if (isAbsolute) {
              // If this is absolute, then just pop it the ".." off and remain at root
              ++shift;
              break;
            }
            // Fall through
          default:
            ++segmentCount;
            if (shift > 0) {
              segments[i - shift] = segments[i];
            }
            break;
        }
      }
      return segmentCount;
    }
  }
}
