/*
 * Copyright (c) 2012 Stanford University
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIM ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <stdio.h>
#include <stdlib.h>

#include <iostream>
#include <string>

#include <oriutil/debug.h>
#include <oriutil/oricrypt.h>
#include <oriutil/stream.h>
#include <ori/mergestate.h>

using namespace std;

/********************************************************************
 *
 *
 * MergeState
 *
 *
 ********************************************************************/

MergeState::MergeState()
{
}

MergeState::~MergeState()
{
}

void
MergeState::setParents(ObjectHash p1, ObjectHash p2)
{
    parents.first = p1;
    parents.second = p2;
}

pair<ObjectHash, ObjectHash>
MergeState::getParents() const
{
    return parents;
}

string
MergeState::getBlob() const
{
    strwstream ss;

    if (!parents.second.isEmpty()) {
        ss.writeUInt8(2);
        ss.writeHash(parents.first);
        ss.writeHash(parents.second);
    } else {
        PANIC(); // Both parents must be set
    }

    return ss.str();
}

void
MergeState::fromBlob(const string &blob)
{
    strstream ss(blob);

    uint8_t numParents = ss.readUInt8();
    if (numParents == 2) {
        ss.readHash(parents.first);
        ss.readHash(parents.second);
    } else {
        PANIC(); // Both parents must be set
    }

    // Verify that everything is set!
}

ObjectHash
MergeState::hash() const
{
    return OriCrypt_HashString(getBlob());
}
