/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

#include "qmf/engine/ObjectImpl.h"
#include "qmf/engine/ValueImpl.h"
#include "qmf/engine/BrokerProxyImpl.h"
#include <qpid/sys/Time.h>

using namespace std;
using namespace qmf::engine;
using namespace qpid::sys;
using qpid::framing::Buffer;

ObjectImpl::ObjectImpl(const SchemaObjectClass* type) : objectClass(type), broker(0), createTime(uint64_t(Duration(EPOCH, now()))), destroyTime(0), lastUpdatedTime(createTime)
{
    int propCount = objectClass->getPropertyCount();
    int statCount = objectClass->getStatisticCount();
    int idx;

    for (idx = 0; idx < propCount; idx++) {
        const SchemaProperty* prop = objectClass->getProperty(idx);
        properties[prop->getName()] = ValuePtr(new Value(prop->getType()));
    }

    for (idx = 0; idx < statCount; idx++) {
        const SchemaStatistic* stat = objectClass->getStatistic(idx);
        statistics[stat->getName()] = ValuePtr(new Value(stat->getType()));
    }
}

ObjectImpl::ObjectImpl(const SchemaObjectClass* type, BrokerProxyImpl* b, Buffer& buffer, bool prop, bool stat, bool managed) :
    objectClass(type), broker(b), createTime(0), destroyTime(0), lastUpdatedTime(0)
{
    int idx;

    if (managed) {
        lastUpdatedTime = buffer.getLongLong();
        createTime = buffer.getLongLong();
        destroyTime = buffer.getLongLong();
        objectId.reset(ObjectIdImpl::factory(buffer));
    }

    if (prop) {
        int propCount = objectClass->getPropertyCount();
        set<string> excludes;
        parsePresenceMasks(buffer, excludes);
        for (idx = 0; idx < propCount; idx++) {
            const SchemaProperty* prop = objectClass->getProperty(idx);
            if (excludes.count(prop->getName()) != 0) {
                properties[prop->getName()] = ValuePtr(new Value(prop->getType()));
            } else {
                Value* pval = ValueImpl::factory(prop->getType(), buffer);
                properties[prop->getName()] = ValuePtr(pval);
            }
        }
    }

    if (stat) {
        int statCount = objectClass->getStatisticCount();
        for (idx = 0; idx < statCount; idx++) {
            const SchemaStatistic* stat = objectClass->getStatistic(idx);
            Value* sval = ValueImpl::factory(stat->getType(), buffer);
            statistics[stat->getName()] = ValuePtr(sval);
        }
    }
}

Object* ObjectImpl::factory(const SchemaObjectClass* type, BrokerProxyImpl* b, Buffer& buffer, bool prop, bool stat, bool managed)
{
    ObjectImpl* impl(new ObjectImpl(type, b, buffer, prop, stat, managed));
    return new Object(impl);
}

ObjectImpl::~ObjectImpl()
{
}

void ObjectImpl::destroy()
{
    destroyTime = uint64_t(Duration(EPOCH, now()));
    // TODO - flag deletion
}

Value* ObjectImpl::getValue(const string& key) const
{
    map<string, ValuePtr>::const_iterator iter;

    iter = properties.find(key);
    if (iter != properties.end())
        return iter->second.get();

    iter = statistics.find(key);
    if (iter != statistics.end())
        return iter->second.get();

    return 0;
}

void ObjectImpl::invokeMethod(const string& methodName, const Value* inArgs, void* context) const
{
    if (broker != 0 && objectId.get() != 0)
        broker->sendMethodRequest(objectId.get(), objectClass, methodName, inArgs, context);
}

void ObjectImpl::merge(const Object& from)
{
    for (map<string, ValuePtr>::const_iterator piter = from.impl->properties.begin();
         piter != from.impl->properties.end(); piter++)
        properties[piter->first] = piter->second;
    for (map<string, ValuePtr>::const_iterator siter = from.impl->statistics.begin();
         siter != from.impl->statistics.end(); siter++)
        statistics[siter->first] = siter->second;
}

void ObjectImpl::parsePresenceMasks(Buffer& buffer, set<string>& excludeList)
{
    int propCount = objectClass->getPropertyCount();
    excludeList.clear();
    uint8_t bit = 0;
    uint8_t mask = 0;

    for (int idx = 0; idx < propCount; idx++) {
        const SchemaProperty* prop = objectClass->getProperty(idx);
        if (prop->isOptional()) {
            if (bit == 0) {
                mask = buffer.getOctet();
                bit = 1;
            }
            if ((mask & bit) == 0)
                excludeList.insert(string(prop->getName()));
            if (bit == 0x80)
                bit = 0;
            else
                bit = bit << 1;
        }
    }
}

void ObjectImpl::encodeSchemaKey(qpid::framing::Buffer& buffer) const
{
    buffer.putShortString(objectClass->getClassKey()->getPackageName());
    buffer.putShortString(objectClass->getClassKey()->getClassName());
    buffer.putBin128(const_cast<uint8_t*>(objectClass->getClassKey()->getHash()));
}

void ObjectImpl::encodeManagedObjectData(qpid::framing::Buffer& buffer) const
{
    buffer.putLongLong(lastUpdatedTime);
    buffer.putLongLong(createTime);
    buffer.putLongLong(destroyTime);
    objectId->impl->encode(buffer);
}

void ObjectImpl::encodeProperties(qpid::framing::Buffer& buffer) const
{
    int propCount = objectClass->getPropertyCount();
    uint8_t bit = 0;
    uint8_t mask = 0;
    ValuePtr value;

    for (int idx = 0; idx < propCount; idx++) {
        const SchemaProperty* prop = objectClass->getProperty(idx);
        if (prop->isOptional()) {
            value = properties[prop->getName()];
            if (bit == 0)
                bit = 1;
            if (!value->isNull())
                mask |= bit;
            if (bit == 0x80) {
                buffer.putOctet(mask);
                bit = 0;
                mask = 0;
            } else
                bit = bit << 1;
        }
    }
    if (bit != 0) {
        buffer.putOctet(mask);
    }

    for (int idx = 0; idx < propCount; idx++) {
        const SchemaProperty* prop = objectClass->getProperty(idx);
        value = properties[prop->getName()];
        if (!prop->isOptional() || !value->isNull()) {
            value->impl->encode(buffer);
        }
    }
}

void ObjectImpl::encodeStatistics(qpid::framing::Buffer& buffer) const
{
    int statCount = objectClass->getStatisticCount();
    for (int idx = 0; idx < statCount; idx++) {
        const SchemaStatistic* stat = objectClass->getStatistic(idx);
        ValuePtr value = statistics[stat->getName()];
        value->impl->encode(buffer);
    }
}

//==================================================================
// Wrappers
//==================================================================

Object::Object(const SchemaObjectClass* type) : impl(new ObjectImpl(type)) {}
Object::Object(ObjectImpl* i) : impl(i) {}
Object::Object(const Object& from) : impl(new ObjectImpl(*(from.impl))) {}
Object::~Object() { delete impl; }
void Object::destroy() { impl->destroy(); }
const ObjectId* Object::getObjectId() const { return impl->getObjectId(); }
void Object::setObjectId(ObjectId* oid) { impl->setObjectId(oid); }
const SchemaObjectClass* Object::getClass() const { return impl->getClass(); }
Value* Object::getValue(const char* key) const { return impl->getValue(key); }
void Object::invokeMethod(const char* m, const Value* a, void* c) const { impl->invokeMethod(m, a, c); }
bool Object::isDeleted() const { return impl->isDeleted(); }
void Object::merge(const Object& from) { impl->merge(from); }

