/*
 * Copyright (C) 2015 The Android Open Source Project
 *
 * 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.
 */

#ifndef ART_CMDLINE_TOKEN_RANGE_H_
#define ART_CMDLINE_TOKEN_RANGE_H_

#include <assert.h>
#include <algorithm>
#include <memory>
#include <string>
#include <vector>

#include "android-base/strings.h"

namespace art {
// A range of tokens to make token matching algorithms easier.
//
// We try really hard to avoid copying and store only a pointer and iterators to the
// interiors of the vector, so a typical copy constructor never ends up doing a deep copy.
// It is up to the user to play nice and not to mutate the strings in-place.
//
// Tokens are only copied if a mutating operation is performed (and even then only
// if it *actually* mutates the token).
struct TokenRange {
  // Short-hand for a vector of strings. A single string and a token is synonymous.
  using TokenList = std::vector<std::string>;

  // Copying-from-vector constructor.
  explicit TokenRange(const TokenList& token_list)
    : token_list_(new TokenList(token_list)),
      begin_(token_list_->begin()),
      end_(token_list_->end())
  {}

  // Copying-from-iterator constructor
  template <typename ForwardIterator>
  TokenRange(ForwardIterator it_begin, ForwardIterator it_end)
    : token_list_(new TokenList(it_begin, it_end)),
      begin_(token_list_->begin()),
      end_(token_list_->end())
  {}

#if 0
  // Copying-from-vector constructor.
  TokenRange(const TokenList& token_list ATTRIBUTE_UNUSED,
             TokenList::const_iterator it_begin,
             TokenList::const_iterator it_end)
    : token_list_(new TokenList(it_begin, it_end)),
      begin_(token_list_->begin()),
      end_(token_list_->end()) {
    assert(it_begin >= token_list.begin());
    assert(it_end <= token_list.end());
  }
#endif

  // Copying from char array constructor, convertings into tokens (strings) along the way.
  TokenRange(const char* token_list[], size_t length)
    : token_list_(new TokenList(&token_list[0], &token_list[length])),
      begin_(token_list_->begin()),
      end_(token_list_->end())
  {}

  // Non-copying move-from-vector constructor. Takes over the token vector.
  explicit TokenRange(TokenList&& token_list)
    : token_list_(new TokenList(std::forward<TokenList>(token_list))),
      begin_(token_list_->begin()),
      end_(token_list_->end())
  {}

  // Non-copying constructor. Retain reference to existing list of tokens.
  TokenRange(const std::shared_ptr<TokenList>& token_list,
             TokenList::const_iterator it_begin,
             TokenList::const_iterator it_end)
    : token_list_(token_list),
      begin_(it_begin),
      end_(it_end) {
    assert(it_begin >= token_list->begin());
    assert(it_end <= token_list->end());
  }

  // Non-copying copy constructor.
  TokenRange(const TokenRange&) = default;

  // Non-copying move constructor.
  TokenRange(TokenRange&&) = default;

  // Non-copying constructor. Retains reference to an existing list of tokens, with offset.
  explicit TokenRange(const std::shared_ptr<TokenList>& token_list)
    : token_list_(token_list),
      begin_(token_list_->begin()),
      end_(token_list_->end())
  {}

  // Iterator type for begin() and end(). Guaranteed to be a RandomAccessIterator.
  using iterator = TokenList::const_iterator;

  // Iterator type for const begin() and const end(). Guaranteed to be a RandomAccessIterator.
  using const_iterator = iterator;

  // Create a token range by splitting a string. Each separator gets their own token.
  // Since the separator are retained as tokens, it might be useful to call
  // RemoveToken afterwards.
  static TokenRange Split(const std::string& string, std::initializer_list<char> separators) {
    TokenList new_token_list;

    std::string tok;
    for (auto&& c : string) {
      for (char sep : separators) {
        if (c == sep) {
          // We spotted a separator character.
          // Push back everything before the last separator as a new token.
          // Push back the separator as a token.
          if (!tok.empty()) {
            new_token_list.push_back(tok);
            tok = "";
          }
          new_token_list.push_back(std::string() + sep);
        } else {
          // Build up the token with another character.
          tok += c;
        }
      }
    }

    if (!tok.empty()) {
      new_token_list.push_back(tok);
    }

    return TokenRange(std::move(new_token_list));
  }

  // A RandomAccessIterator to the first element in this range.
  iterator begin() const {
    return begin_;
  }

  // A RandomAccessIterator to one past the last element in this range.
  iterator end() const {
    return end_;
  }

  // The size of the range, i.e. how many tokens are in it.
  size_t Size() const {
    return std::distance(begin_, end_);
  }

  // Are there 0 tokens in this range?
  bool IsEmpty() const {
    return Size() > 0;
  }

  // Look up a token by it's offset.
  const std::string& GetToken(size_t offset) const {
    assert(offset < Size());
    return *(begin_ + offset);
  }

  // Does this token range equal the other range?
  // Equality is defined as having both the same size, and
  // each corresponding token being equal.
  bool operator==(const TokenRange& other) const {
    if (this == &other) {
      return true;
    }

    if (Size() != other.Size()) {
      return false;
    }

    return std::equal(begin(), end(), other.begin());
  }

  // Look up the token at the requested index.
  const std::string& operator[](int index) const {
    assert(index >= 0 && static_cast<size_t>(index) < Size());
    return *(begin() + index);
  }

  // Does this current range start with the other range?
  bool StartsWith(const TokenRange& other) const {
    if (this == &other) {
      return true;
    }

    if (Size() < other.Size()) {
      return false;
    }

    auto& smaller = Size() < other.Size() ? *this : other;
    auto& greater = Size() < other.Size() ? other : *this;

    return std::equal(smaller.begin(), smaller.end(), greater.begin());
  }

  // Remove all characters 'c' from each token, potentially copying the underlying tokens.
  TokenRange RemoveCharacter(char c) const {
    TokenList new_token_list(begin(), end());

    bool changed = false;
    for (auto&& token : new_token_list) {
      auto it = std::remove_if(token.begin(), token.end(), [&](char ch) {
        if (ch == c) {
          changed = true;
          return true;
        }
        return false;
      });
      token.erase(it, token.end());
    }

    if (!changed) {
      return *this;
    }

    return TokenRange(std::move(new_token_list));
  }

  // Remove all tokens matching this one, potentially copying the underlying tokens.
  TokenRange RemoveToken(const std::string& token) {
    return RemoveIf([&](const std::string& tok) { return tok == token; });
  }

  // Discard all empty tokens, potentially copying the underlying tokens.
  TokenRange DiscardEmpty() const {
    return RemoveIf([](const std::string& token) { return token.empty(); });
  }

  // Create a non-copying subset of this range.
  // Length is trimmed so that the Slice does not go out of range.
  TokenRange Slice(size_t offset, size_t length = std::string::npos) const {
    assert(offset < Size());

    if (length != std::string::npos && offset + length > Size()) {
      length = Size() - offset;
    }

    iterator it_end;
    if (length == std::string::npos) {
      it_end = end();
    } else {
      it_end = begin() + offset + length;
    }

    return TokenRange(token_list_, begin() + offset, it_end);
  }

  // Try to match the string with tokens from this range.
  // Each token is used to match exactly once (after which the next token is used, and so on).
  // The matching happens from left-to-right in a non-greedy fashion.
  // If the currently-matched token is the wildcard, then the new outputted token will
  // contain as much as possible until the next token is matched.
  //
  // For example, if this == ["a:", "_", "b:] and "_" is the match string, then
  // MatchSubstrings on "a:foob:" will yield: ["a:", "foo", "b:"]
  //
  // Since the string matching can fail (e.g. ["foo"] against "bar"), then this
  // function can fail, in which cause it will return null.
  std::unique_ptr<TokenRange> MatchSubstrings(const std::string& string,
                                              const std::string& wildcard) const {
    TokenList new_token_list;

    size_t wildcard_idx = std::string::npos;
    size_t string_idx = 0;

    // Function to push all the characters matched as a wildcard so far
    // as a brand new token. It resets the wildcard matching.
    // Empty wildcards are possible and ok, but only if wildcard matching was on.
    auto maybe_push_wildcard_token = [&]() {
      if (wildcard_idx != std::string::npos) {
        size_t wildcard_length = string_idx - wildcard_idx;
        std::string wildcard_substr = string.substr(wildcard_idx, wildcard_length);
        new_token_list.push_back(std::move(wildcard_substr));

        wildcard_idx = std::string::npos;
      }
    };

    for (iterator it = begin(); it != end(); ++it) {
      const std::string& tok = *it;

      if (tok == wildcard) {
        maybe_push_wildcard_token();
        wildcard_idx = string_idx;
        continue;
      }

      size_t next_token_idx = string.find(tok);
      if (next_token_idx == std::string::npos) {
        // Could not find token at all
        return nullptr;
      } else if (next_token_idx != string_idx && wildcard_idx == std::string::npos) {
        // Found the token at a non-starting location, and we weren't
        // trying to parse the wildcard.
        return nullptr;
      }

      new_token_list.push_back(string.substr(next_token_idx, tok.size()));
      maybe_push_wildcard_token();
      string_idx += tok.size();
    }

    size_t remaining = string.size() - string_idx;
    if (remaining > 0) {
      if (wildcard_idx == std::string::npos) {
        // Some characters were still remaining in the string,
        // but it wasn't trying to match a wildcard.
        return nullptr;
      }
    }

    // If some characters are remaining, the rest must be a wildcard.
    string_idx += remaining;
    maybe_push_wildcard_token();

    return std::make_unique<TokenRange>(std::move(new_token_list));
  }

  // Do a quick match token-by-token, and see if they match.
  // Any tokens with a wildcard in them are only matched up until the wildcard.
  // If this is true, then the wildcard matching later on can still fail, so this is not
  // a guarantee that the argument is correct, it's more of a strong hint that the
  // user-provided input *probably* was trying to match this argument.
  //
  // Returns how many tokens were either matched (or ignored because there was a
  // wildcard present). 0 means no match. If the size() tokens are returned.
  size_t MaybeMatches(const TokenRange& token_list, const std::string& wildcard) const {
    auto token_it = token_list.begin();
    auto token_end = token_list.end();
    auto name_it = begin();
    auto name_end = end();

    size_t matched_tokens = 0;

    while (token_it != token_end && name_it != name_end) {
      // Skip token matching when the corresponding name has a wildcard in it.
      const std::string& name = *name_it;

      size_t wildcard_idx = name.find(wildcard);
      if (wildcard_idx == std::string::npos) {  // No wildcard present
        // Did the definition token match the user token?
        if (name != *token_it) {
          return matched_tokens;
        }
      } else {
        std::string name_prefix = name.substr(0, wildcard_idx);

        // Did the user token start with the up-to-the-wildcard prefix?
        if (!StartsWith(*token_it, name_prefix)) {
          return matched_tokens;
        }
      }

      ++token_it;
      ++name_it;
      ++matched_tokens;
    }

    // If we got this far, it's either a full match or the token list was too short.
    return matched_tokens;
  }

  // Flatten the token range by joining every adjacent token with the separator character.
  // e.g. ["hello", "world"].join('$') == "hello$world"
  std::string Join(char separator) const {
    TokenList tmp(begin(), end());
    return android::base::Join(tmp, separator);
    // TODO: Join should probably take an offset or iterators
  }

 private:
  static bool StartsWith(const std::string& larger, const std::string& smaller) {
    if (larger.size() >= smaller.size()) {
      return std::equal(smaller.begin(), smaller.end(), larger.begin());
    }

    return false;
  }

  template <typename TPredicate>
  TokenRange RemoveIf(const TPredicate& predicate) const {
    // If any of the tokens in the token lists are empty, then
    // we need to remove them and compress the token list into a smaller one.
    bool remove = false;
    for (auto it = begin_; it != end_; ++it) {
      auto&& token = *it;

      if (predicate(token)) {
        remove = true;
        break;
      }
    }

    // Actually copy the token list and remove the tokens that don't match our predicate.
    if (remove) {
      auto token_list = std::make_shared<TokenList>(begin(), end());
      TokenList::iterator new_end =
          std::remove_if(token_list->begin(), token_list->end(), predicate);
      token_list->erase(new_end, token_list->end());

      assert(token_list_->size() > token_list->size() && "Nothing was actually removed!");

      return TokenRange(token_list);
    }

    return *this;
  }

  const std::shared_ptr<std::vector<std::string>> token_list_;
  const iterator begin_;
  const iterator end_;
};
}  // namespace art

#endif  // ART_CMDLINE_TOKEN_RANGE_H_
