/*
 * 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 <algorithm>

#include "ignite/odbc/system/odbc_constants.h"
#include "ignite/odbc/app/parameter.h"
#include "ignite/odbc/utility.h"

namespace ignite
{
    namespace odbc
    {
        namespace app
        {
            Parameter::Parameter() :
                buffer(),
                sqlType(),
                columnSize(),
                decDigits(),
                nullData(false),
                storedData()
            {
                // No-op.
            }

            Parameter::Parameter(const ApplicationDataBuffer& buffer, int16_t sqlType,
                size_t columnSize, int16_t decDigits) :
                buffer(buffer),
                sqlType(sqlType),
                columnSize(columnSize),
                decDigits(decDigits),
                nullData(false),
                storedData()
            {
                // No-op.
            }

            Parameter::Parameter(const Parameter& other) :
                buffer(other.buffer),
                sqlType(other.sqlType),
                columnSize(other.columnSize),
                decDigits(other.decDigits),
                nullData(other.nullData),
                storedData(other.storedData)
            {
                // No-op.
            }

            Parameter::~Parameter()
            {
                // No-op.
            }

            Parameter& Parameter::operator=(const Parameter &other)
            {
                buffer = other.buffer;
                sqlType = other.sqlType;
                columnSize = other.columnSize;
                decDigits = other.decDigits;

                return *this;
            }

            void Parameter::Write(impl::binary::BinaryWriterImpl& writer, int offset, SqlUlen idx) const
            {
                if (buffer.GetInputSize() == SQL_NULL_DATA)
                {
                    writer.WriteNull();

                    return;
                }

                // Buffer to use to get data.
                ApplicationDataBuffer buf(buffer);
                buf.SetByteOffset(offset);
                buf.SetElementOffset(idx);

                SqlLen storedDataLen = static_cast<SqlLen>(storedData.size());

                if (buffer.IsDataAtExec())
                {
                    buf = ApplicationDataBuffer(buffer.GetType(),
                        const_cast<int8_t*>(&storedData[0]), storedDataLen, &storedDataLen);
                }

                switch (sqlType)
                {
                    case SQL_CHAR:
                    case SQL_VARCHAR:
                    case SQL_LONGVARCHAR:
                    {
                        utility::WriteString(writer, buf.GetString(columnSize));
                        break;
                    }

                    case SQL_SMALLINT:
                    {
                        writer.WriteObject<int16_t>(buf.GetInt16());
                        break;
                    }

                    case SQL_INTEGER:
                    {
                        writer.WriteObject<int32_t>(buf.GetInt32());
                        break;
                    }

                    case SQL_FLOAT:
                    {
                        writer.WriteObject<float>(buf.GetFloat());
                        break;
                    }

                    case SQL_DOUBLE:
                    {
                        writer.WriteObject<double>(buf.GetDouble());
                        break;
                    }

                    case SQL_TINYINT:
                    {
                        writer.WriteObject<int8_t>(buf.GetInt8());
                        break;
                    }

                    case SQL_BIT:
                    {
                        writer.WriteObject<bool>(buf.GetInt8() != 0);
                        break;
                    }

                    case SQL_BIGINT:
                    {
                        writer.WriteObject<int64_t>(buf.GetInt64());
                        break;
                    }

                    case SQL_TYPE_DATE:
                    case SQL_DATE:
                    {
                        writer.WriteDate(buf.GetDate());
                        break;
                    }

                    case SQL_TYPE_TIMESTAMP:
                    case SQL_TIMESTAMP:
                    {
                        writer.WriteTimestamp(buf.GetTimestamp());
                        break;
                    }

                    case SQL_TYPE_TIME:
                    case SQL_TIME:
                    {
                        writer.WriteTime(buf.GetTime());
                        break;
                    }

                    case SQL_BINARY:
                    case SQL_VARBINARY:
                    case SQL_LONGVARBINARY:
                    {
                        const ApplicationDataBuffer& constRef = buf;

                        const SqlLen* resLenPtr = constRef.GetResLen();

                        if (!resLenPtr)
                            break;

                        int32_t paramLen = static_cast<int32_t>(*resLenPtr);

                        writer.WriteInt8Array(reinterpret_cast<const int8_t*>(constRef.GetData()), paramLen);

                        break;
                    }

                    case SQL_GUID:
                    {
                        writer.WriteGuid(buf.GetGuid());

                        break;
                    }

                    case SQL_DECIMAL:
                    {
                        common::Decimal dec;
                        buf.GetDecimal(dec);

                        utility::WriteDecimal(writer, dec);

                        break;
                    }

                    default:
                        break;
                }
            }

            ApplicationDataBuffer& Parameter::GetBuffer()
            {
                return buffer;
            }

            const ApplicationDataBuffer& Parameter::GetBuffer() const
            {
                return buffer;
            }

            void Parameter::ResetStoredData()
            {
                storedData.clear();

                if (buffer.IsDataAtExec())
                    storedData.reserve(buffer.GetDataAtExecSize());
            }

            bool Parameter::IsDataReady() const
            {
                return !buffer.IsDataAtExec() ||
                       storedData.size() == buffer.GetDataAtExecSize();
            }

            void Parameter::PutData(void* data, SqlLen len)
            {
                if (len == SQL_DEFAULT_PARAM)
                    return;

                if (len == SQL_NULL_DATA)
                {
                    nullData = true;

                    return;
                }

                if (buffer.GetType() == type_traits::OdbcNativeType::AI_CHAR ||
                    buffer.GetType() == type_traits::OdbcNativeType::AI_BINARY)
                {
                    SqlLen slen = len;

                    if (buffer.GetType() == type_traits::OdbcNativeType::AI_CHAR && slen == SQL_NTSL)
                    {
                        const char* str = reinterpret_cast<char*>(data);

                        slen = strlen(str);
                    }

                    if (slen <= 0)
                        return;

                    size_t beginPos = storedData.size();

                    storedData.resize(storedData.size() + static_cast<size_t>(slen));

                    memcpy(&storedData[beginPos], data, static_cast<size_t>(slen));

                    return;
                }

                size_t dataSize = buffer.GetDataAtExecSize();

                storedData.resize(dataSize);

                memcpy(&storedData[0], data, dataSize);
            }
        }
    }
}
