/* 
 * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; version 2 of the
 * License.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301  USA
 */

#include "stdafx.h"

#include <grts/structs.db.query.h>

#include <grtpp_util.h>
#include "sqlide/recordset_be.h"
#include "db_query_Resultset.h"

//================================================================================
// db_query_Resultset

db_query_Resultset::ImplData::ImplData(db_query_ResultsetRef aself, boost::shared_ptr<Recordset> rset)
: self(dynamic_cast<db_query_Resultset*>(aself.valueptr())), recordset(rset), cursor(0)
{ 
  const int last_column= recordset->get_column_count();
  for (int i = 0; i < last_column; i++)
  {
    column_by_name[recordset->get_column_caption(i)]= i;
    
    std::string type;
    switch (recordset->get_column_type(i))
    {
      case bec::GridModel::UnknownType: type= "unknown"; break;
      case bec::GridModel::StringType: type= "string"; break;
      case bec::GridModel::NumericType: type= "numeric"; break;
      case bec::GridModel::FloatType: type= "float"; break;
      case bec::GridModel::DatetimeType: type= "datetime"; break;
      case bec::GridModel::BlobType: type= "blob"; break;
    }
    
    db_query_ResultsetColumnRef column(aself->get_grt());
    
    column->owner(aself);
    column->name(recordset->get_column_caption(i));
    column->columnType(type);
    
    self->columns().insert(column);
  }
}


db_query_ResultsetRef grtwrap_recordset(GrtObjectRef owner, Recordset::Ref rset)
{
  db_query_ResultsetRef object(owner.get_grt());

  db_query_Resultset::ImplData *data= new db_query_Resultset::ImplData(object, rset);
  
  object->owner(owner);

  object->set_data(data);

  return object;
}



void db_query_Resultset::init()
{
  // _data init is delayed and done by grtwrap_recordset
}

db_query_Resultset::~db_query_Resultset()
{
  delete _data;
}


void db_query_Resultset::set_data(ImplData *data)
{
  _data= data;
}

grt::IntegerRef db_query_Resultset::currentRow() const
{
  if (_data)
    return grt::IntegerRef((grt::IntegerRef::storage_type)_data->cursor);
  return grt::IntegerRef();
}

grt::StringRef db_query_Resultset::sql() const
{
  return _data ? grt::StringRef(_data->recordset->generator_query()) : grt::StringRef();
}

grt::IntegerRef db_query_Resultset::rowCount() const
{
  return _data ? grt::IntegerRef(_data->recordset->count()) : grt::IntegerRef();
}

grt::DoubleRef db_query_Resultset::floatFieldValue(long column)
{
  double value;
  if (_data && column >= 0 && column < _data->recordset->get_column_count() &&
      _data->recordset->get_field(_data->cursor, column, value))
    return grt::DoubleRef(value);
  return grt::DoubleRef(); // NULL
}


grt::DoubleRef db_query_Resultset::floatFieldValueByName(const std::string &column)
{
  double value;
  if (_data && _data->column_by_name.find(column) != _data->column_by_name.end())
  {
    if (_data->recordset->get_field(_data->cursor, _data->column_by_name[column], value))
      return grt::DoubleRef(value);
  }
  return grt::DoubleRef(); // NULL  
}


grt::IntegerRef db_query_Resultset::goToFirstRow()
{
  if (_data)
  {
    _data->cursor= 0;
    return grt::IntegerRef((int) _data->cursor < _data->recordset->count());
  }
  return grt::IntegerRef(0);
}


grt::IntegerRef db_query_Resultset::goToLastRow()
{
  if (_data && _data->recordset->count() > 0)
  {
    _data->cursor= _data->recordset->count()-1;
    return grt::IntegerRef(1);
  }
  return grt::IntegerRef(0);
}


grt::IntegerRef db_query_Resultset::goToRow(long row)
{
  if (_data && row >= 0 && row < _data->recordset->count())
  {
    _data->cursor= row;
    return grt::IntegerRef(1);
  }
  return grt::IntegerRef(0);
}


grt::IntegerRef db_query_Resultset::intFieldValue(long column)
{
  long long value;
  if (_data && column >= 0 && column < _data->recordset->get_column_count() &&
      _data->recordset->get_field(bec::NodeId(_data->cursor), (int)column, value))
    return grt::IntegerRef((grt::IntegerRef::storage_type)value);
  return grt::IntegerRef(); // NULL  
}


grt::IntegerRef db_query_Resultset::intFieldValueByName(const std::string &column)
{
  long long value;
  if (_data && _data->column_by_name.find(column) != _data->column_by_name.end())
  {
    if (_data->recordset->get_field(bec::NodeId(_data->cursor), _data->column_by_name[column], value))
      return grt::IntegerRef((grt::IntegerRef::storage_type)value);
  }
  return grt::IntegerRef(); // NULL  
}


grt::IntegerRef db_query_Resultset::nextRow()
{
  if (_data && (int) _data->cursor < _data->recordset->count() - 1)
  {
    ++_data->cursor;
    return grt::IntegerRef(1);
  }
  return grt::IntegerRef(0);
}


grt::IntegerRef db_query_Resultset::previousRow()
{
  if (_data && _data->cursor > 0)
  {
    --_data->cursor;
    return grt::IntegerRef(1);
  }
  return grt::IntegerRef(0);
}


grt::IntegerRef db_query_Resultset::refresh()
{
  if (_data)
    _data->recordset->refresh();

  return grt::IntegerRef(0);
}


grt::StringRef db_query_Resultset::stringFieldValue(long column)
{
  std::string value;
  if (_data && column >= 0 && column < _data->recordset->get_column_count() &&
      _data->recordset->get_field_repr_no_truncate(bec::NodeId(_data->cursor), (int)column, value))
    return grt::StringRef(value);
  return grt::StringRef(); // NULL    
}


grt::StringRef db_query_Resultset::stringFieldValueByName(const std::string &column)
{
  std::string value;
  if (_data && _data->column_by_name.find(column) != _data->column_by_name.end())
  {
    if (_data->recordset->get_field_repr_no_truncate(bec::NodeId(_data->cursor), _data->column_by_name[column], value))
      return grt::StringRef(value);
  }
  return grt::StringRef(); // NULL    
}

grt::IntegerRef db_query_Resultset::saveFieldValueToFile(long column, const std::string &file)
{
  if (_data && column >= 0 && column < _data->recordset->get_column_count())
  {
    _data->recordset->save_to_file(bec::NodeId(_data->cursor), (int)column, file);
    return grt::IntegerRef(1);
  }
  return grt::IntegerRef(0);
}
