/*
 *
 *    Copyright (c) 2013-2017 Nest Labs, Inc.
 *    All rights reserved.
 *
 *    Licensed 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.
 */

/**
 *    @file
 *      This file implements methods for the Nest Weave Status Report
 *      profile.
 */

#include <Weave/Core/WeaveCore.h>
#include <Weave/Core/WeaveMessageLayer.h>
#include <Weave/Profiles/ProfileCommon.h>
#include <Weave/Support/CodeUtils.h>

using namespace ::nl::Weave;
using namespace ::nl::Weave::TLV;
using namespace ::nl::Weave::Profiles;
using namespace ::nl::Weave::Profiles::Common;
using namespace ::nl::Weave::Profiles::StatusReporting;

StatusReport::StatusReport(void)
{
    mProfileId = 0;
    mStatusCode = 0;
    mError = WEAVE_NO_ERROR;
}

StatusReport::~StatusReport(void)
{
    mProfileId = 0;
    mStatusCode = 0;
    mError = WEAVE_NO_ERROR;
}

WEAVE_ERROR StatusReport::init(uint32_t aProfileId, uint16_t aCode, ReferencedTLVData *aInfo)
{
    mProfileId = aProfileId;
    mStatusCode = aCode;
    mError = WEAVE_NO_ERROR;

    if (aInfo)
        mAdditionalInfo = *aInfo;

    return WEAVE_NO_ERROR;
}

WEAVE_ERROR StatusReport::init(WEAVE_ERROR aError)
{
    if (aError == WEAVE_NO_ERROR)
    {
        mProfileId = kWeaveProfile_Common;
        mStatusCode = kStatus_Success;
    }

    else
    {
        mProfileId = kWeaveProfile_Common;
        mStatusCode = kStatus_InternalError;
        mError = aError;
    }

    return WEAVE_NO_ERROR;
}

WEAVE_ERROR StatusReport::pack(PacketBuffer *aBuffer)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    MessageIterator i(aBuffer);
    TLVWriter writer;

    i.append();

    err = i.write32(mProfileId);
    SuccessOrExit(err);

    err = i.write16(mStatusCode);
    SuccessOrExit(err);

    /*
     * the assumption here is that EITHER there's
     * an error code that wants to be included as
     * metadata OR there's additional info passed
     * in at initialization time, which may include
     * an error, OR there's none of the above, in
     * which case the else clause her writes nothing
     */

    if (mError != WEAVE_NO_ERROR)
    {
        writer.Init(aBuffer);

        err = StartMetaData(writer);
        SuccessOrExit(err);

        err = AddErrorCode(writer, mError);
        SuccessOrExit(err);

        err = EndMetaData(writer);
        SuccessOrExit(err);

        /*
         * this is a bit of a hack. we basically set this
         * so that packedLength() below will return the right
         * number at least if we call it AFTER the thing has
         * been packed. it's not clear we ever use this.
         */

        mAdditionalInfo.theLength = writer.GetLengthWritten();
    }

    else
    {
        err = mAdditionalInfo.pack(i);
    }

exit:
    return err;
}

inline uint16_t StatusReport::packedLength(void)
{
    return sizeof(mProfileId)+sizeof(mStatusCode)+mAdditionalInfo.theLength;
}

WEAVE_ERROR StatusReport::parse(PacketBuffer *aBuffer, StatusReport &aDestination)
{
    WEAVE_ERROR err;
    MessageIterator i(aBuffer);

    err = i.read32(&aDestination.mProfileId);
    SuccessOrExit(err);

    err = i.read16(&aDestination.mStatusCode);
    SuccessOrExit(err);

    err = ReferencedTLVData::parse(i, aDestination.mAdditionalInfo);

exit:
    return err;
}

bool StatusReport::operator == (const StatusReport &another) const
{
    return ((mProfileId == another.mProfileId) && (mStatusCode == another.mStatusCode));
}

/*
 * the universal, gold standard for success is
 * <Nest Labs> : <Common Profile> : <Success>
 */

bool StatusReport::success(void)
{
    return(mProfileId == kWeaveProfile_Common && mStatusCode == kStatus_Success);
}

WEAVE_ERROR StatusReport::StartMetaData(nl::Weave::TLV::TLVWriter &aWriter)
{
    TLVType metaDataContainer;

    return aWriter.StartContainer(AnonymousTag, kTLVType_Structure, metaDataContainer);
}

WEAVE_ERROR StatusReport::EndMetaData(nl::Weave::TLV::TLVWriter &aWriter)
{
    WEAVE_ERROR err;
    TLVType metaDataContainer = kTLVType_Structure;

    err = aWriter.EndContainer(metaDataContainer);
    SuccessOrExit(err);

    err = aWriter.Finalize();

exit:
    return err;
}

WEAVE_ERROR StatusReport::AddErrorCode(nl::Weave::TLV::TLVWriter &aWriter, WEAVE_ERROR aError)
{
    return aWriter.Put(CommonTag(kTag_SystemErrorCode), aError);
}
