/*
 * NMSTL, the Networking, Messaging, Servers, and Threading Library for C++
 * Copyright (c) 2002 Massachusetts Institute of Technology
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#include <cmath>

#include <iostream>
#include <iterator>

#include <nmstl/serial>

using namespace nmstl;
using namespace std;

struct my_thingy {
    int number;
    map<string, string> xlate;

    string as_string() const {
        return "{" + to_string(number) + " is " + to_string(xlate) + "}";
    }

    NMSTL_SIMPLY_SERIALIZABLE(my_thingy, << number << xlate );

#if 0
    // Alternatively:
    void freeze(oserial &out) const {
        out << number << xlate;
    }
    void unfreeze(iserial &in) {
        in >> number >> xlate;
    }
#endif
};
NMSTL_TO_STRING(my_thingy);

int main() {
    vector<my_thingy> nums(3);

    nums[0].number = 3;
    nums[0].xlate["en"] = "three";
    nums[0].xlate["de"] = "drei";
    nums[0].xlate["jp"] = "san";

    nums[1].number = 6;
    nums[1].xlate["en"] = "six";
    nums[1].xlate["de"] = "sechs";
    nums[1].xlate["ch"] = "liu";

    nums[2].number = 9;
    nums[2].xlate["en"] = "nine";
    nums[2].xlate["ch"] = "jiu";
    nums[2].xlate["es"] = "nueve";

    bool t = true;
    bool f = false;

    vector<string> vs;
    vs.push_back("FOO");
    vs.push_back("BAR");
    vs.push_back("BAZ");

    map<int, string> ms;
    ms[2] = "TWO";
    ms[1] = "ONE";
    ms[9] = "NINE";

    const char *modestrs[] = { "typesafe", "readable", "binary", "compact" };
    int modes[] = { oserial::typesafe, oserial::readable, oserial::binary, oserial::compact };

    int testints[] = { 0, 0x3F, 0x40, 0x7F, 0x80, -42, 0x7FFFFFFF, 0x80000000 };
    for (unsigned int i = 0; i < sizeof testints / sizeof testints[0]; ++i) {
        oserialstring out(oserial::compact);
        out << testints[i];
        string str = out.str();

        int t;

        iserialstring in(str);
        in >> t;

        cout << "Compact representation of " << testints[i] << " is " << to_hex_string(str.data(), str.length()) << " (deserializes to " << t << ")" << endl;
	if (!in) cout << " - deserialization failed!" << endl;
    }

    for (int i = 0; i < 3; ++i) {
        int mode = modes[i];
        cout << "Using " << modestrs[i] << " mode..." << endl;

        oserialstring out(mode);
        out <<
            "Here's a string; yup!" << 
            "" <<
            t <<
            f <<
            12345 <<
            M_PI <<
            vs <<
            ms <<
            nums <<
            ntime::now();

        string str = out.str();

        cout << "Serial representation: \"" << to_escaped_string(str.data(), str.length()) << "\"" << endl;

        iserialstring iss(out.str());

        string s, s2;
        int j;
        double d;
        vector<string> vv;
        map<int, string> mm;
        vector<my_thingy> nn;
        ntime tt;
        bool t, f;
        iss >> s >> s2 >> t >> f >> j >> d >> vv >> mm >> nn >> tt;

        if (!iss) {
            cout << "Failed: " << iss.stat() << endl;
        } else {
            cout << s << "/" << t << "/" << f << "/" << j << "/" << d << endl;
            cout << to_string(vv) << endl;
            cout << to_string(mm) << endl;
            cout << to_string(nn) << endl;
            cout << "time: " << to_string(tt) << endl;
        }

        cout << endl;
    }
}
