/*
 * Copyright 2009 Funambol, Inc.
 *
 * 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.
 */

/* $Id$ */

#include "Logger/LoggerMacroses.h"
#include "serverexchange/MessageFactory.h"
#include "serverexchange/SendingStrategy.h"

using namespace NS_DM_Client;
using namespace NS_DM_Client::NS_Common;
using namespace NS_DM_Client::NS_Communication;

#define ACCEPT_BOTH_MIMES      "application/vnd.syncml.dm+xml, application/vnd.syncml.dm+wbxml"
#define PROPERTY_ACCEPT        "Accept"
#define PROPERTY_CONTENT_TYPE  "Content-Type"
#define PROPERTY_HMAC          "X-Syncml-Hmac"

static const char * c_LogName = "SendingStrategy";


SendingStrategy::SendingStrategy(ConnectionInfo &info, ISession &session) :
    m_connInfo(info),
    m_session(session)
{
}


SendingStrategy::Status SendingStrategy::Send(NS_SyncMLCommand::CommandStorage &cmds)
{
    MessageFactory factory(m_connInfo);
    int bytes_left = m_connInfo.settings.MaxMsgSize - factory.MessageSizeWithoutBody();
    
    for (int i=0; i<cmds.Size(); ++i)
    {
        if (bytes_left < 0)
            return NeedToSendLO;
        
        cmds[i]->Prepare();
        
        if (hasItemsSmallerThanMaxObjSize(cmds[i]))
        {
            int cmdsize = factory.AddCommand(cmds[i]);
            bytes_left -= cmdsize;
        }
        else
        {
            return NeedToSendLO;
        }
    }
    if (bytes_left < 0)
    {
        GDLDEBUG("bytes left: %d; switch to sending LO", bytes_left);
        return NeedToSendLO;
    }
    
    Funambol::StringBuffer *pSyncMLMessage = factory.GetMessage(!m_connInfo.IsInLOMode());
    GDLDEBUG("get message from factory, SB - %x", pSyncMLMessage);
    if (pSyncMLMessage)
    {
        m_session.SendMessage(*pSyncMLMessage);
        SAFE_DELETE(pSyncMLMessage);
    }
    else
    {
        GDLERROR("Failed to create message");
    }
    return SendingSucceded;
}


bool SendingStrategy::hasItemsSmallerThanMaxObjSize(NS_SyncMLCommand::SCommandPtr ptrCmd)
{
    if (!ptrCmd.get() || !ptrCmd->Internal().get() || !ptrCmd->Internal()->getItems())
    {
        return true;
    }

    Funambol::ArrayList *items = ptrCmd->Internal()->getItems();
    for (int i=0; i<items->size(); ++i)
    {
        Funambol::Item *item = (Funambol::Item *)items->get(i);
        if (item && item->getData())
        {
            const char *pData = item->getData()->getData();
            if (pData && (strlen(pData) > m_connInfo.settings.MaxObjSize))
            {
                GDLDEBUG("Check failed on item: %s [%d bytes]", ptrCmd->Internal()->getName(), strlen(pData));
                return false; // found item with data larger than MaxObjSize param
            }
        }
    }
    return true;
}
