/***************************************************************************
                         FLTableMetaData.cpp
                         -------------------
begin                : Mon Jul 2 2001
copyright            : (C) 2001-2005 by InfoSiAL S.L.
email                : mail@infosial.com
***************************************************************************/
/***************************************************************************
 *   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.               *
 ***************************************************************************/
/***************************************************************************
   Este  programa es software libre. Puede redistribuirlo y/o modificarlo
   bajo  los  términos  de  la  Licencia  Pública General de GNU   en  su
   versión 2, publicada  por  la  Free  Software Foundation.
 ***************************************************************************/

#include "FLTableMetaData.h"
#include "FLFieldMetaData.h"
#include "FLRelationMetaData.h"
#include "FLCompoundKey.h"

// dpinelo
FLTableMetaDataPrivate::FLTableMetaDataPrivate( const QString & n, const QString & a, const QString & q, 
const QString &schema ) :
    name_( n.lower() ), alias_( a ), compoundKey_( 0 ), query_( q ), schema_( schema ) {
  fieldList_ = new FLTableMetaData::FLFieldMetaDataList( 41 );
  fieldList_->setAutoDelete( true );
}

FLTableMetaDataPrivate::~FLTableMetaDataPrivate() {
  delete fieldList_;
  if ( compoundKey_ )
    delete compoundKey_;
}

// dpinelo
FLTableMetaData::FLTableMetaData( const QString & n, const QString & a, const QString & q,
								const QString & schema ) : QObject( 0, n.lower() ) {
	// dpinelo
  d = new FLTableMetaDataPrivate( n, a, q, schema );
}

FLTableMetaData::~FLTableMetaData() {
  if ( d )
    delete d;
}

void FLTableMetaData::addFieldMD( FLFieldMetaData * f ) {
  if ( f ) {
    f->setMetadata( this );
    d->fieldList_->insert( f->d->name_.lower(), f );
    d->addFieldName( f->d->name_ );
    d->formatAlias( f );
    if ( f->d->type_ == FLFieldMetaData::Unlock )
      d->fieldsNamesUnlock_.append( f->d->name_ );
  }
}

void FLTableMetaData::removeFieldMD( const QString & fN ) {
  if ( fN.isEmpty() )
    return;
  d->fieldList_->remove( fN.lower() );
  d->removeFieldName( fN );
}

QString FLTableMetaData::fieldNameToAlias( const QString & fN ) const {
  if ( fN.isEmpty() )
    return fN;

  QMap<QString, QString>::const_iterator it( d->fieldAliasMap_.find( fN.lower() ) );
  if ( it != d->fieldAliasMap_.end() )
    return *it;

  return fN;
}

QString FLTableMetaData::fieldAliasToName( const QString & aN ) const {
  if ( aN.isEmpty() )
    return aN;

  QMap<QString, QString>::const_iterator it( d->aliasFieldMap_.find( aN ) );
  if ( it != d->aliasFieldMap_.end() )
    return *it;

  return aN;
}

int FLTableMetaData::fieldType( const QString & fN ) const {
  if ( fN.isEmpty() )
    return QVariant::Invalid;

  FLFieldMetaData *field = d->fieldList_->find( fN.lower() );
  if ( field )
    return field->d->type_;

  return QVariant::Invalid;
}

int FLTableMetaData::fieldLength( const QString & fN ) const {
  if ( fN.isEmpty() )
    return 0;

  FLFieldMetaData *field = d->fieldList_->find( fN.lower() );
  if ( field )
    return field->d->length_;

  return 0;
}

int FLTableMetaData::fieldPartInteger( const QString & fN ) const {
  if ( fN.isEmpty() )
    return 0;

  FLFieldMetaData *field = d->fieldList_->find( fN.lower() );
  if ( field )
    return field->d->partInteger_;

  return 0;
}

int FLTableMetaData::fieldPartDecimal( const QString & fN ) const {
  if ( fN.isEmpty() )
    return 0;

  FLFieldMetaData *field = d->fieldList_->find( fN.lower() );
  if ( field )
    return field->d->partDecimal_;

  return 0;
}

bool FLTableMetaData::fieldIsPrimaryKey( const QString & fN ) const {
  if ( fN.isEmpty() )
    return false;

  FLFieldMetaData *field = d->fieldList_->find( fN.lower() );
  if ( field )
    return field->d->isPrimaryKey_;

  return false;
}

QString FLTableMetaData::primaryKey( bool prefixTable ) const {
  QDictIterator<FLFieldMetaData> it( *d->fieldList_ );
  for ( ; it.current(); ++it )
	// dpinelo: Modificado para la lógica propia de las querys
    if ( ( *it ) && ( *it )->d->isPrimaryKey_ ) {
	  if ( ! this->isQuery() ) {
		  return ( prefixTable ? d->name_ + "." + ( *it )->d->name_ : ( *it )->d->name_ );
	  } else {
		  return ( ( *it )->d->name_ );
	  }
	}
  return QString::null;
}

bool FLTableMetaData::fieldIsIndex( const QString & fN ) const {
  if ( fN.isEmpty() )
    return false;

  FLFieldMetaData *field = d->fieldList_->find( fN.lower() );
  if ( field )
    return field->d->isIndex_;

  return false;
}

bool FLTableMetaData::fieldIsUnique( const QString & fN ) const {
  if ( fN.isEmpty() )
    return false;

  FLFieldMetaData *field = d->fieldList_->find( fN.lower() );
  if ( field )
    return field->d->isUnique_;

  return false;
}

bool FLTableMetaData::fieldIsCounter( const QString & fN ) const {
  if ( fN.isEmpty() )
    return false;

  FLFieldMetaData *field = d->fieldList_->find( fN.lower() );
  if ( field )
    return field->d->contador_;

  return false;
}

bool FLTableMetaData::fieldAllowNull( const QString & fN ) const {
  if ( fN.isEmpty() )
    return false;

  FLFieldMetaData *field = d->fieldList_->find( fN.lower() );
  if ( field )
    return field->d->allowNull_;

  return false;
}

bool FLTableMetaData::fieldCalculated( const QString & fN ) const {
  if ( fN.isEmpty() )
    return false;

  FLFieldMetaData *field = d->fieldList_->find( fN.lower() );
  if ( field )
    return field->d->calculated_;

  return false;
}

bool FLTableMetaData::fieldVisible( const QString & fN ) const {
  if ( fN.isEmpty() )
    return false;

  FLFieldMetaData *field = d->fieldList_->find( fN.lower() );
  if ( field )
    return field->d->visible_;

  return false;
}

FLFieldMetaData *FLTableMetaData::field( const QString & fN ) const {
  if ( fN.isEmpty() )
    return 0;

  return d->fieldList_->find( fN.lower() );
}

QString FLTableMetaData::fieldTableM1( const QString & fN ) const {
  if ( fN.isEmpty() )
    return QString::null;

  FLFieldMetaData *field = d->fieldList_->find( fN.lower() );
  if ( field && field->d->relationM1_ )
    return field->d->relationM1_->foreignTable();

  return QString::null;
}

QString FLTableMetaData::fieldForeignFieldM1( const QString & fN ) const {
  if ( fN.isEmpty() )
    return QString::null;

  FLFieldMetaData *field = d->fieldList_->find( fN.lower() );
  if ( field && field->d->relationM1_ )
    return field->d->relationM1_->foreignField();

  return QString::null;
}

FLRelationMetaData * FLTableMetaData::relation( const QString & fN, const QString & fFN, const QString & fTN ) const {
  if ( fN.isEmpty() )
    return 0;

  FLFieldMetaData *field = d->fieldList_->find( fN.lower() );
  if ( field ) {
    if ( field->d->relationM1_ && field->d->relationM1_->foreignField() == fFN.lower() &&
         field->d->relationM1_->foreignTable() == fTN.lower() )
      return field->d->relationM1_;
    FLFieldMetaData::FLRelationMetaDataList * relationList = field->d->relationList_;
    if ( !relationList )
      return 0;
    if ( relationList->isEmpty() )
      return 0;
    FLRelationMetaData * r;
    QPtrListIterator<FLRelationMetaData> itR( *relationList );
    while ( ( r = itR.current() ) != 0 ) {
      ++itR;
      if ( r->foreignField() == fFN.lower() && r->foreignTable() == fTN.lower() )
        return r;
    }
  }

  return 0;
}

FLTableMetaData::FLFieldMetaDataList *
FLTableMetaData::fieldListOfCompoundKey( const QString & fN ) const {
  if ( d->compoundKey_ && d->compoundKey_->hasField( fN ) )
    return d->compoundKey_->fieldList();
  return 0;
}

QString FLTableMetaData::fieldList( bool prefixTable ) const {

	if ( !prefixTable )
		return d->fieldsNames_;

	QStringList fieldsNames = QStringList::split( ",", d->fieldsNames_ );
	QString ret;
	for ( QStringList::Iterator it = fieldsNames.begin(); it != fieldsNames.end(); ++it ) {
		if ( !( *it ).contains( "." ) ) {
			// dpinelo
			if ( d->schema_.isEmpty() ) {
				if ( ret.isEmpty() )
					ret +=  d->name_ + "." + ( *it );
				else
					ret += "," +  d->name_ + "." + ( *it );
			} else {
				if ( ret.isEmpty() )
					ret +=  d->schema_ + "." + d->name_ + "." + ( *it );
				else
					ret += "," + d->schema_ + "." + d->name_ + "." + ( *it );
			}
		}
	}

	return ret;
}

void FLTableMetaData::setName( const QString & n ) {
  QObject::setName( n );
  d->name_ = n;
}

void FLTableMetaDataPrivate::formatAlias( FLFieldMetaData * f ) {
  if ( !f )
    return;

  QString alias( f->alias() );
  QString field( f->name().lower() );
  QMap<QString, QString>::const_iterator it( aliasFieldMap_.find( alias ) );

  if ( it != aliasFieldMap_.end() ) {
    alias += "(" + QString::number( aliasFieldMap_.size() + 1 ) + ")";
    f->d->alias_ = alias;
  }

  aliasFieldMap_[ alias ] = field;
  fieldAliasMap_[ field ] = alias;
}

void FLTableMetaDataPrivate::addFieldName( const QString & n ) {
  if ( fieldsNames_.isEmpty() )
    fieldsNames_ += n.lower();
  else
    fieldsNames_ += "," + n.lower();
}

void FLTableMetaDataPrivate::removeFieldName( const QString & n ) {
  if ( !fieldsNames_.isEmpty() ) {
    QStringList list( QStringList::split( ",", fieldsNames_ ) );
    list.remove( n.lower() );
    fieldsNames_ = list.join( "," );
  }
}

