/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef SkRecordPattern_DEFINED
#define SkRecordPattern_DEFINED

#include "include/private/SkTLogic.h"
#include "src/core/SkRecord.h"

namespace SkRecords {

// First, some matchers.  These match a single command in the SkRecord,
// and may hang onto some data from it.  If so, you can get the data by calling .get().

// Matches a command of type T, and stores that command.
template <typename T>
class Is {
public:
    Is() : fPtr(nullptr) {}

    typedef T type;
    type* get() { return fPtr; }

    bool operator()(T* ptr) {
        fPtr = ptr;
        return true;
    }

    template <typename U>
    bool operator()(U*) {
        fPtr = nullptr;
        return false;
    }

private:
    type* fPtr;
};

// Matches any command that draws, and stores its paint.
class IsDraw {
public:
    IsDraw() : fPaint(nullptr) {}

    typedef SkPaint type;
    type* get() { return fPaint; }

    template <typename T>
    std::enable_if_t<(T::kTags & kDrawWithPaint_Tag) == kDrawWithPaint_Tag, bool>
    operator()(T* draw) {
        fPaint = AsPtr(draw->paint);
        return true;
    }

    template <typename T>
    std::enable_if_t<(T::kTags & kDrawWithPaint_Tag) == kDraw_Tag, bool> operator()(T* draw) {
        fPaint = nullptr;
        return true;
    }

    template <typename T>
    std::enable_if_t<!(T::kTags & kDraw_Tag), bool> operator()(T* draw) {
        fPaint = nullptr;
        return false;
    }

private:
    // Abstracts away whether the paint is always part of the command or optional.
    template <typename T> static T* AsPtr(SkRecords::Optional<T>& x) { return x; }
    template <typename T> static T* AsPtr(T& x) { return &x; }

    type* fPaint;
};

// Matches if Matcher doesn't.  Stores nothing.
template <typename Matcher>
struct Not {
    template <typename T>
    bool operator()(T* ptr) { return !Matcher()(ptr); }
};

// Matches if any of First or Rest... does.  Stores nothing.
template <typename First, typename... Rest>
struct Or {
    template <typename T>
    bool operator()(T* ptr) { return First()(ptr) || Or<Rest...>()(ptr); }
};
template <typename First>
struct Or<First> {
    template <typename T>
    bool operator()(T* ptr) { return First()(ptr); }
};


// Greedy is a special matcher that greedily matches Matcher 0 or more times.  Stores nothing.
template <typename Matcher>
struct Greedy {
    template <typename T>
    bool operator()(T* ptr) { return Matcher()(ptr); }
};

// Pattern matches each of its matchers in order.
//
// This is the main entry point to pattern matching, and so provides a couple of extra API bits:
//  - search scans through the record to look for matches;
//  - first, second, third, ... return the data stored by their respective matchers in the pattern.

template <typename... Matchers> class Pattern;

template <> class Pattern<> {
public:
    // Bottoms out recursion.  Just return whatever i the front decided on.
    int match(SkRecord*, int i) { return i; }
};

template <typename First, typename... Rest>
class Pattern<First, Rest...> {
public:
    // If this pattern matches the SkRecord starting from i,
    // return the index just past the end of the pattern, otherwise return 0.
    SK_ALWAYS_INLINE int match(SkRecord* record, int i) {
        i = this->matchFirst(&fFirst, record, i);
        return i > 0 ? fRest.match(record, i) : 0;
    }

    // Starting from *end, walk through the SkRecord to find the first span matching this pattern.
    // If there is no such span, return false.  If there is, return true and set [*begin, *end).
    SK_ALWAYS_INLINE bool search(SkRecord* record, int* begin, int* end) {
        for (*begin = *end; *begin < record->count(); ++(*begin)) {
            *end = this->match(record, *begin);
            if (*end != 0) {
                return true;
            }
        }
        return false;
    }

    // TODO: some sort of smart get<i>()
    template <typename T> T* first()  { return fFirst.get();   }
    template <typename T> T* second() { return fRest.template first<T>();  }
    template <typename T> T* third()  { return fRest.template second<T>(); }
    template <typename T> T* fourth() { return fRest.template third<T>();  }

private:
    // If first isn't a Greedy, try to match at i once.
    template <typename T>
    int matchFirst(T* first, SkRecord* record, int i) {
        if (i < record->count()) {
            if (record->mutate(i, *first)) {
                return i+1;
            }
        }
        return 0;
    }

    // If first is a Greedy, walk i until it doesn't match.
    template <typename T>
    int matchFirst(Greedy<T>* first, SkRecord* record, int i) {
        while (i < record->count()) {
            if (!record->mutate(i, *first)) {
                return i;
            }
            i++;
        }
        return 0;
    }

    First            fFirst;
    Pattern<Rest...> fRest;
};

}  // namespace SkRecords

#endif//SkRecordPattern_DEFINED
