/*
 * 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 AAPT_UTIL_H
#define AAPT_UTIL_H

#include "BigBuffer.h"
#include "StringPiece.h"

#include <androidfw/ResourceTypes.h>
#include <functional>
#include <memory>
#include <ostream>
#include <string>
#include <vector>

namespace aapt {
namespace util {

std::vector<std::string> split(const StringPiece& str, char sep);
std::vector<std::string> splitAndLowercase(const StringPiece& str, char sep);

/**
 * Returns true if the string starts with prefix.
 */
template <typename T>
bool stringStartsWith(const BasicStringPiece<T>& str, const BasicStringPiece<T>& prefix) {
    if (str.size() < prefix.size()) {
        return false;
    }
    return str.substr(0, prefix.size()) == prefix;
}

/**
 * Returns true if the string ends with suffix.
 */
template <typename T>
bool stringEndsWith(const BasicStringPiece<T>& str, const BasicStringPiece<T>& suffix) {
    if (str.size() < suffix.size()) {
        return false;
    }
    return str.substr(str.size() - suffix.size(), suffix.size()) == suffix;
}

/**
 * Creates a new StringPiece16 that points to a substring
 * of the original string without leading or trailing whitespace.
 */
StringPiece16 trimWhitespace(const StringPiece16& str);

/**
 * UTF-16 isspace(). It basically checks for lower range characters that are
 * whitespace.
 */
inline bool isspace16(char16_t c) {
    return c < 0x0080 && isspace(c);
}

/**
 * Returns an iterator to the first character that is not alpha-numeric and that
 * is not in the allowedChars set.
 */
StringPiece16::const_iterator findNonAlphaNumericAndNotInSet(const StringPiece16& str,
        const StringPiece16& allowedChars);

/**
 * Makes a std::unique_ptr<> with the template parameter inferred by the compiler.
 * This will be present in C++14 and can be removed then.
 */
template <typename T, class... Args>
std::unique_ptr<T> make_unique(Args&&... args) {
    return std::unique_ptr<T>(new T{std::forward<Args>(args)...});
}

/**
 * Writes a set of items to the std::ostream, joining the times with the provided
 * separator.
 */
template <typename Iterator>
::std::function<::std::ostream&(::std::ostream&)> joiner(Iterator begin, Iterator end,
        const char* sep) {
    return [begin, end, sep](::std::ostream& out) -> ::std::ostream& {
        for (auto iter = begin; iter != end; ++iter) {
            if (iter != begin) {
                out << sep;
            }
            out << *iter;
        }
        return out;
    };
}

inline ::std::function<::std::ostream&(::std::ostream&)> formatSize(size_t size) {
    return [size](::std::ostream& out) -> ::std::ostream& {
        constexpr size_t K = 1024u;
        constexpr size_t M = K * K;
        constexpr size_t G = M * K;
        if (size < K) {
            out << size << "B";
        } else if (size < M) {
            out << (double(size) / K) << " KiB";
        } else if (size < G) {
            out << (double(size) / M) << " MiB";
        } else {
            out << (double(size) / G) << " GiB";
        }
        return out;
    };
}

/**
 * Helper method to extract a string from a StringPool.
 */
inline StringPiece16 getString(const android::ResStringPool& pool, size_t idx) {
    size_t len;
    const char16_t* str = pool.stringAt(idx, &len);
    if (str != nullptr) {
        return StringPiece16(str, len);
    }
    return StringPiece16();
}

class StringBuilder {
public:
    StringBuilder& append(const StringPiece16& str);
    const std::u16string& str() const;
    const std::string& error() const;
    operator bool() const;

private:
    std::u16string mStr;
    bool mQuote = false;
    bool mTrailingSpace = false;
    std::string mError;
};

inline const std::u16string& StringBuilder::str() const {
    return mStr;
}

inline const std::string& StringBuilder::error() const {
    return mError;
}

inline StringBuilder::operator bool() const {
    return mError.empty();
}

/**
 * Converts a UTF8 string to a UTF16 string.
 */
std::u16string utf8ToUtf16(const StringPiece& utf8);
std::string utf16ToUtf8(const StringPiece16& utf8);

/**
 * Writes the entire BigBuffer to the output stream.
 */
bool writeAll(std::ostream& out, const BigBuffer& buffer);

/*
 * Copies the entire BigBuffer into a single buffer.
 */
std::unique_ptr<uint8_t[]> copy(const BigBuffer& buffer);

/**
 * A Tokenizer implemented as an iterable collection. It does not allocate
 * any memory on the heap nor use standard containers.
 */
template <typename Char>
class Tokenizer {
public:
    class iterator {
    public:
        iterator(const iterator&) = default;
        iterator& operator=(const iterator&) = default;

        iterator& operator++();
        BasicStringPiece<Char> operator*();
        bool operator==(const iterator& rhs) const;
        bool operator!=(const iterator& rhs) const;

    private:
        friend class Tokenizer<Char>;

        iterator(BasicStringPiece<Char> s, Char sep, BasicStringPiece<Char> tok);

        BasicStringPiece<Char> str;
        Char separator;
        BasicStringPiece<Char> token;
    };

    Tokenizer(BasicStringPiece<Char> str, Char sep);
    iterator begin();
    iterator end();

private:
    const iterator mBegin;
    const iterator mEnd;
};

template <typename Char>
inline Tokenizer<Char> tokenize(BasicStringPiece<Char> str, Char sep) {
    return Tokenizer<Char>(str, sep);
}

template <typename Char>
typename Tokenizer<Char>::iterator& Tokenizer<Char>::iterator::operator++() {
    const Char* start = token.end();
    const Char* end = str.end();
    if (start == end) {
        token.assign(token.end(), 0);
        return *this;
    }

    start += 1;
    const Char* current = start;
    while (current != end) {
        if (*current == separator) {
            token.assign(start, current - start);
            return *this;
        }
        ++current;
    }
    token.assign(start, end - start);
    return *this;
}

template <typename Char>
inline BasicStringPiece<Char> Tokenizer<Char>::iterator::operator*() {
    return token;
}

template <typename Char>
inline bool Tokenizer<Char>::iterator::operator==(const iterator& rhs) const {
    // We check equality here a bit differently.
    // We need to know that the addresses are the same.
    return token.begin() == rhs.token.begin() && token.end() == rhs.token.end();
}

template <typename Char>
inline bool Tokenizer<Char>::iterator::operator!=(const iterator& rhs) const {
    return !(*this == rhs);
}

template <typename Char>
inline Tokenizer<Char>::iterator::iterator(BasicStringPiece<Char> s, Char sep,
                                           BasicStringPiece<Char> tok) :
        str(s), separator(sep), token(tok) {
}

template <typename Char>
inline typename Tokenizer<Char>::iterator Tokenizer<Char>::begin() {
    return mBegin;
}

template <typename Char>
inline typename Tokenizer<Char>::iterator Tokenizer<Char>::end() {
    return mEnd;
}

template <typename Char>
inline Tokenizer<Char>::Tokenizer(BasicStringPiece<Char> str, Char sep) :
        mBegin(++iterator(str, sep, BasicStringPiece<Char>(str.begin() - 1, 0))),
        mEnd(str, sep, BasicStringPiece<Char>(str.end(), 0)) {
}

} // namespace util

/**
 * Stream operator for functions. Calls the function with the stream as an argument.
 * In the aapt namespace for lookup.
 */
inline ::std::ostream& operator<<(::std::ostream& out,
                                  ::std::function<::std::ostream&(::std::ostream&)> f) {
    return f(out);
}

} // namespace aapt

#endif // AAPT_UTIL_H
