#include "UnitTest++.h"

#include "test_utils.hh"

#include "geners/valarrayIO.hh"
#include "geners/StringArchive.hh"
#include "geners/Record.hh"
#include "geners/Reference.hh"

using namespace gs;
using namespace std;

namespace {
    class Persistent3
    {
    public:
        inline Persistent3(int n=0) : n_(n) {}

        inline bool operator==(const Persistent3& r) const
            {return n_ == r.n_;}
        inline bool operator!=(const Persistent3& r) const
            {return !(*this == r);}

        inline Persistent3& operator+=(const int& r)
        {
            n_ += r;
            return *this;
        }

        inline ClassId classId() const {return ClassId(*this);}

        inline bool write(std::ostream& os) const
        {
            write_pod(os, n_);
            return !os.bad() && !os.fail();
        }

        static inline const char* classname() {return "gs::test::Persistent3";}
        static inline unsigned version() {return 1;}
        static inline Persistent3* read(const ClassId& id, std::istream& in)
        {
            assert(id == ClassId::makeId<Persistent3>());
            int n;
            read_pod(in, &n);
            if (in.fail())
                return 0;
            else
                return new Persistent3(n);
        }

    private:
        int n_;
    };
}

namespace {
    TEST(valarrayIO_1)
    {
        const unsigned sz = 10;
        StringArchive ar0;

        valarray<int> v0(sz);
        for (unsigned i=0; i<sz; ++i)
            v0[i] = static_cast<int>(i*2 + 23);
        CHECK_EQUAL(sz, v0.size());

        ar0 << Record(v0, "v0", "top");

        valarray<int> v0_read;
        Reference<valarray<int> >(ar0, "v0", "top").restore(0,&v0_read);

        CHECK_EQUAL(sz, v0_read.size());
        for (unsigned i=0; i<sz; ++i)
            CHECK_EQUAL(v0[i], v0_read[i]);
    }

    TEST(valarrayIO_2)
    {
        const unsigned sz = 17;
        StringArchive ar0;

        valarray<Persistent3> v0(sz);
        for (unsigned i=0; i<sz; ++i)
            v0[i] = Persistent3(i*2 + 23);
        CHECK_EQUAL(sz, v0.size());

        ar0 << Record(v0, "v0", "top");

        Reference<valarray<Persistent3> > ref(ar0, "v0", "top");
        CHECK(ref.unique());

        valarray<Persistent3> v0_read;
        ref.restore(0,&v0_read);

        CHECK_EQUAL(sz, v0_read.size());
        for (unsigned i=0; i<sz; ++i)
            CHECK(v0[i] == v0_read[i]);
    }
}
