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

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

struct Student {
    Student() : name(), age(), height(), canSwim() {}
    Student(const std::string name, unsigned age, double height, bool canSwim) :
        name(name), age(age), height(height), canSwim(canSwim)
    {}

    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 {
    Group() : groupName(), students() {}
    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() : x_(), y_() {}
    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() : radius_() {}
    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() : width_(), height_() {}
    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() : shapes_() {}
    ~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();
}
