#include "archiver.h"
#include <iostream>
#include <vector>

//////////////////////////////////////////////////////////////////////////////
// Test1: simple object

struct Student {
    std::string name;
    unsigned age;
    double height;
    bool canSwim;
};

template <typename Archiver>
Archiver& operator&(Archiver& ar, Student& s) {
    ar.StartObject();
    ar.Member("name") & s.name;
    ar.Member("age") & s.age;
    ar.Member("height") & s.height;
    ar.Member("canSwim") & s.canSwim;
    return ar.EndObject();
}

std::ostream& operator<<(std::ostream& os, const Student& s) {
    return os << s.name << " " << s.age << " " << s.height << " " << s.canSwim;
}

void test1() {
    std::string json;

    // Serialize
    {
        Student s = { "Lua", 9, 150.5, true };

        JsonWriter writer;
        writer & s;
        json = writer.GetString();
        std::cout << json << std::endl;
    }

    // Deserialize
    {
        Student s;
        JsonReader reader(json.c_str());
        reader & s;
        std::cout << s << std::endl;
    }
}

//////////////////////////////////////////////////////////////////////////////
// Test2: std::vector <=> JSON array
// 
// You can map a JSON array to other data structures as well

struct Group {
    std::string groupName;
    std::vector<Student> students;
};

template <typename Archiver>
Archiver& operator&(Archiver& ar, Group& g) {
    ar.StartObject();
    
    ar.Member("groupName");
    ar & g.groupName;

    ar.Member("students");
    size_t studentCount = g.students.size();
    ar.StartArray(&studentCount);
    if (ar.IsReader)
        g.students.resize(studentCount);
    for (size_t i = 0; i < studentCount; i++)
        ar & g.students[i];
    ar.EndArray();

    return ar.EndObject();
}

std::ostream& operator<<(std::ostream& os, const Group& g) {
    os << g.groupName << std::endl;
    for (std::vector<Student>::const_iterator itr = g.students.begin(); itr != g.students.end(); ++itr)
        os << *itr << std::endl;
    return os;
}

void test2() {
    std::string json;

    // Serialize
    {
        Group g;
        g.groupName = "Rainbow";

        Student s1 = { "Lua", 9, 150.5, true };
        Student s2 = { "Mio", 7, 120.0, false };
        g.students.push_back(s1);
        g.students.push_back(s2);

        JsonWriter writer;
        writer & g;
        json = writer.GetString();
        std::cout << json << std::endl;
    }

    // Deserialize
    {
        Group g;
        JsonReader reader(json.c_str());
        reader & g;
        std::cout << g << std::endl;
    }
}

//////////////////////////////////////////////////////////////////////////////
// Test3: polymorphism & friend
//
// Note that friendship is not necessary but make things simpler.

class Shape {
public:
    virtual ~Shape() {}
    virtual const char* GetType() const = 0;
    virtual void Print(std::ostream& os) const = 0;

protected:
    Shape() {}
    Shape(double x, double y) : x_(x), y_(y) {}

    template <typename Archiver>
    friend Archiver& operator&(Archiver& ar, Shape& s);

    double x_, y_;
};

template <typename Archiver>
Archiver& operator&(Archiver& ar, Shape& s) {
    ar.Member("x") & s.x_;
    ar.Member("y") & s.y_;
    return ar;
}

class Circle : public Shape {
public:
    Circle() {}
    Circle(double x, double y, double radius) : Shape(x, y), radius_(radius) {}
    ~Circle() {}

    const char* GetType() const { return "Circle"; }

    void Print(std::ostream& os) const {
        os << "Circle (" << x_ << ", " << y_ << ")" << " radius = " << radius_;
    }

private:
    template <typename Archiver>
    friend Archiver& operator&(Archiver& ar, Circle& c);

    double radius_;
};

template <typename Archiver>
Archiver& operator&(Archiver& ar, Circle& c) {
    ar & static_cast<Shape&>(c);
    ar.Member("radius") & c.radius_;
    return ar;
}

class Box : public Shape {
public:
    Box() {}
    Box(double x, double y, double width, double height) : Shape(x, y), width_(width), height_(height) {}
    ~Box() {}

    const char* GetType() const { return "Box"; }

    void Print(std::ostream& os) const {
        os << "Box (" << x_ << ", " << y_ << ")" << " width = " << width_ << " height = " << height_;
    }

private:
    template <typename Archiver>
    friend Archiver& operator&(Archiver& ar, Box& b);

    double width_, height_;
};

template <typename Archiver>
Archiver& operator&(Archiver& ar, Box& b) {
    ar & static_cast<Shape&>(b);
    ar.Member("width") & b.width_;
    ar.Member("height") & b.height_;
    return ar;
}

class Canvas {
public:
    Canvas() {}
    ~Canvas() { Clear(); }
    
    void Clear() {
        for (std::vector<Shape*>::iterator itr = shapes_.begin(); itr != shapes_.end(); ++itr)
            delete *itr;
    }

    void AddShape(Shape* shape) { shapes_.push_back(shape); }
    
    void Print(std::ostream& os) {
        for (std::vector<Shape*>::iterator itr = shapes_.begin(); itr != shapes_.end(); ++itr) {
            (*itr)->Print(os);
            std::cout << std::endl;
        }
    }

private:
    template <typename Archiver>
    friend Archiver& operator&(Archiver& ar, Canvas& c);

    std::vector<Shape*> shapes_;
};

template <typename Archiver>
Archiver& operator&(Archiver& ar, Shape*& shape) {
    std::string type = ar.IsReader ? "" : shape->GetType();
    ar.StartObject();
    ar.Member("type") & type;
    if (type == "Circle") {
        if (ar.IsReader) shape = new Circle;
        ar & static_cast<Circle&>(*shape);
    }
    else if (type == "Box") {
        if (ar.IsReader) shape = new Box;
        ar & static_cast<Box&>(*shape);
    }
    return ar.EndObject();
}

template <typename Archiver>
Archiver& operator&(Archiver& ar, Canvas& c) {
    size_t shapeCount = c.shapes_.size();
    ar.StartArray(&shapeCount);
    if (ar.IsReader) {
        c.Clear();
        c.shapes_.resize(shapeCount);
    }
    for (size_t i = 0; i < shapeCount; i++)
        ar & c.shapes_[i];
    return ar.EndArray();
}

void test3() {
    std::string json;

    // Serialize
    {
        Canvas c;
        c.AddShape(new Circle(1.0, 2.0, 3.0));
        c.AddShape(new Box(4.0, 5.0, 6.0, 7.0));

        JsonWriter writer;
        writer & c;
        json = writer.GetString();
        std::cout << json << std::endl;
    }

    // Deserialize
    {
        Canvas c;
        JsonReader reader(json.c_str());
        reader & c;
        c.Print(std::cout);
    }
}

//////////////////////////////////////////////////////////////////////////////

int main() {
    test1();
    test2();
    test3();
}
