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

#ifndef SkParticleSerialization_DEFINED
#define SkParticleSerialization_DEFINED

#include "modules/particles/include/SkReflected.h"

#include "include/core/SkString.h"
#include "include/private/SkTArray.h"
#include "src/utils/SkJSON.h"
#include "src/utils/SkJSONWriter.h"

class SkToJsonVisitor : public SkFieldVisitor {
public:
    SkToJsonVisitor(SkJSONWriter& writer) : fWriter(writer) {}

    // Primitives
    void visit(const char* name, float& f) override {
        fWriter.appendFloat(name, f);
    }
    void visit(const char* name, int& i) override {
        fWriter.appendS32(name, i);
    }
    void visit(const char* name, bool& b) override {
        fWriter.appendBool(name, b);
    }
    void visit(const char* name, SkString& s) override {
        if (s.contains('\n')) {
            SkTArray<SkString> lines;
            SkStrSplit(s.c_str(), "\n", kStrict_SkStrSplitMode, &lines);
            fWriter.beginArray(name);
            for (const auto& line : lines) {
                fWriter.appendString(line.c_str());
            }
            fWriter.endArray();
        } else {
            fWriter.appendString(name, s.c_str());
        }
    }
    void visit(const char* name, int& i, const EnumStringMapping* map, int count) override {
        fWriter.appendString(name, EnumToString(i, map, count));
    }

    // Compound types
    void visit(const char* name, SkPoint& p) override {
        fWriter.beginObject(name, false);
        fWriter.appendFloat("x", p.fX);
        fWriter.appendFloat("y", p.fY);
        fWriter.endObject();
    }

    void visit(const char* name, SkColor4f& c) override {
        fWriter.beginArray(name, false);
        fWriter.appendFloat(c.fR);
        fWriter.appendFloat(c.fG);
        fWriter.appendFloat(c.fB);
        fWriter.appendFloat(c.fA);
        fWriter.endArray();
    }

    void visit(sk_sp<SkReflected>& e, const SkReflected::Type* baseType) override {
        fWriter.appendString("Type", e ? e->getType()->fName : "Null");
    }

    void enterObject(const char* name) override { fWriter.beginObject(name); }
    void exitObject()                  override { fWriter.endObject(); }

    int enterArray(const char* name, int oldCount) override {
        fWriter.beginArray(name);
        return oldCount;
    }
    ArrayEdit exitArray() override {
        fWriter.endArray();
        return ArrayEdit();
    }

private:
    SkJSONWriter& fWriter;
};

class SkFromJsonVisitor : public SkFieldVisitor {
public:
    SkFromJsonVisitor(const skjson::Value& v) : fRoot(v) {
        fStack.push_back(&fRoot);
    }

    void visit(const char* name, float& f) override {
        TryParse(get(name), f);
    }
    void visit(const char* name, int& i) override {
        TryParse(get(name), i);
    }
    void visit(const char* name, bool& b) override {
        TryParse(get(name), b);
    }
    void visit(const char* name, SkString& s) override {
        if (const skjson::ArrayValue* lines = get(name)) {
            s.reset();
            bool first = true;
            for (const skjson::StringValue* line : *lines) {
                if (line) {
                    if (!first) {
                        s.append("\n");
                    }
                    s.append(line->begin(), line->size());
                    first = false;
                }
            }
        } else {
            TryParse(get(name), s);
        }
    }
    void visit(const char* name, int& i, const EnumStringMapping* map, int count) override {
        SkString str;
        if (TryParse(get(name), str)) {
            i = StringToEnum(str.c_str(), map, count);
        }
    }

    void visit(const char* name, SkPoint& p) override {
        if (const skjson::ObjectValue* obj = get(name)) {
            TryParse((*obj)["x"], p.fX);
            TryParse((*obj)["y"], p.fY);
        }
    }

    void visit(const char* name, SkColor4f& c) override {
        const skjson::ArrayValue* arr = get(name);
        if (arr && arr->size() == 4) {
            TryParse((*arr)[0], c.fR);
            TryParse((*arr)[1], c.fG);
            TryParse((*arr)[2], c.fB);
            TryParse((*arr)[3], c.fA);
        }
    }

    void visit(sk_sp<SkReflected>& e, const SkReflected::Type* baseType) override {
        const skjson::StringValue* typeString = get("Type");
        const char* type = typeString ? typeString->begin() : "Null";
        e = SkReflected::CreateInstance(type);
    }

    void enterObject(const char* name) override {
        fStack.push_back((const skjson::ObjectValue*)get(name));
    }
    void exitObject() override {
        fStack.pop_back();
    }

    int enterArray(const char* name, int oldCount) override {
        const skjson::ArrayValue* arrVal = get(name);
        fStack.push_back(arrVal);
        fArrayIndexStack.push_back(0);
        return arrVal ? arrVal->size() : 0;
    }
    ArrayEdit exitArray() override {
        fStack.pop_back();
        fArrayIndexStack.pop_back();
        return ArrayEdit();
    }

private:
    const skjson::Value& get(const char* name) {
        if (const skjson::Value* cur = fStack.back()) {
            if (cur->is<skjson::ArrayValue>()) {
                SkASSERT(!name);
                return cur->as<skjson::ArrayValue>()[fArrayIndexStack.back()++];
            } else if (!name) {
                return *cur;
            } else if (cur->is<skjson::ObjectValue>()) {
                return cur->as<skjson::ObjectValue>()[name];
            }
        }
        static skjson::NullValue gNull;
        return gNull;
    }

    static bool TryParse(const skjson::Value& v, float& f) {
        if (const skjson::NumberValue* num = v) {
            f = static_cast<float>(**num);
            return true;
        }
        return false;
    }

    static bool TryParse(const skjson::Value& v, int& i) {
        if (const skjson::NumberValue* num = v) {
            double dbl = **num;
            i = static_cast<int>(dbl);
            return static_cast<double>(i) == dbl;
        }
        return false;
    }

    static bool TryParse(const skjson::Value& v, SkString& s) {
        if (const skjson::StringValue* str = v) {
            s.set(str->begin(), str->size());
            return true;
        }
        return false;
    }

    static bool TryParse(const skjson::Value& v, bool& b) {
        switch (v.getType()) {
        case skjson::Value::Type::kNumber:
            b = SkToBool(*v.as<skjson::NumberValue>());
            return true;
        case skjson::Value::Type::kBool:
            b = *v.as<skjson::BoolValue>();
            return true;
        default:
            break;
        }

        return false;
    }

    const skjson::Value& fRoot;
    SkSTArray<16, const skjson::Value*, true> fStack;
    SkSTArray<16, size_t, true>               fArrayIndexStack;
};

#endif // SkParticleSerialization_DEFINED
