/*
 * RecipeExtrasWidget.cpp is part of Brewtarget, and is Copyright the following
 * authors 2009-2014
 * - Mik Firestone <mikfire@gmail.com>
 * - Peter Buelow <goballstate@gmail.com>
 * - Philip Greggory Lee <rocketman768@gmail.com>
 *
 * Brewtarget 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, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Brewtarget 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, see <http://www.gnu.org/licenses/>.
 */

#include <QDate>
#include "RecipeExtrasWidget.h"
#include "unit.h"
#include "brewtarget.h"
#include "recipe.h"

RecipeExtrasWidget::RecipeExtrasWidget(QWidget* parent)
   : QWidget(parent), recipe(0)
{
   setupUi(this);

   ratingChanged = false;

   connect( lineEdit_age, SIGNAL(editingFinished()), this, SLOT(updateAge()));
   connect( lineEdit_ageTemp, SIGNAL(editingFinished()), this, SLOT(updateAgeTemp()));
   connect( lineEdit_asstBrewer, SIGNAL(editingFinished()), this, SLOT(updateBrewerAsst()) );
   connect( lineEdit_brewer, SIGNAL(editingFinished()), this, SLOT(updateBrewer()) );
   connect( lineEdit_carbVols, SIGNAL(editingFinished()), this, SLOT(updateCarbonation()) );
   connect( lineEdit_primaryAge, SIGNAL(editingFinished()), this, SLOT(updatePrimaryAge()) );
   connect( lineEdit_primaryTemp, SIGNAL(editingFinished()), this, SLOT(updatePrimaryTemp()) );
   connect( lineEdit_secAge, SIGNAL(editingFinished()), this, SLOT(updateSecondaryAge()) );
   connect( lineEdit_secTemp, SIGNAL(editingFinished()), this, SLOT(updateSecondaryTemp()) );
   connect( lineEdit_tertAge, SIGNAL(editingFinished()), this, SLOT(updateTertiaryAge()) );
   connect( lineEdit_tertTemp, SIGNAL(editingFinished()), this, SLOT(updateTertiaryTemp()) );

   connect( spinBox_tasteRating, SIGNAL(valueChanged(int)), this, SLOT(changeRatings(int)) );
   connect( spinBox_tasteRating, SIGNAL(editingFinished()), this, SLOT(updateTasteRating()) );

   connect( dateEdit_date, SIGNAL(dateChanged(const QDate& )), this, SLOT(updateDate(const QDate&)) );

   connect(btTextEdit_notes, SIGNAL(textModified()), this, SLOT(updateNotes()));
   connect(btTextEdit_tasteNotes, SIGNAL(textModified()), this, SLOT(updateTasteNotes()));
}

void RecipeExtrasWidget::setRecipe(Recipe* rec)
{
   if( recipe )
      disconnect( recipe, 0, this, 0 );
   
   if( rec )
   {
      recipe = rec;
      connect( recipe, SIGNAL(changed(QMetaProperty,QVariant)), this, SLOT(changed(QMetaProperty,QVariant)) );
      showChanges();
   }
}

void RecipeExtrasWidget::updateBrewer()
{
   if( recipe == 0 )
      return;

   if ( lineEdit_brewer->isModified() )
      recipe->setBrewer(lineEdit_brewer->text());
}

void RecipeExtrasWidget::updateBrewerAsst()
{
   if( recipe == 0 )
      return;

   if ( lineEdit_asstBrewer->isModified() )
      recipe->setAsstBrewer(lineEdit_asstBrewer->text());
}

void RecipeExtrasWidget::changeRatings(int rating) { ratingChanged = true; }

void RecipeExtrasWidget::updateTasteRating()
{
   if( recipe == 0 )
      return;

   if ( ratingChanged )
   {
      recipe->setTasteRating( (double)(spinBox_tasteRating->value()) );
      ratingChanged = false;
   }
}

void RecipeExtrasWidget::updatePrimaryAge()
{
   if( recipe == 0 )
      return;

   if ( lineEdit_primaryAge->isModified() )
      recipe->setPrimaryAge_days( lineEdit_primaryAge->text().toDouble() );
}

void RecipeExtrasWidget::updatePrimaryTemp()
{
   if( recipe == 0 )
      return;

   if ( lineEdit_primaryTemp->isModified() )
      recipe->setPrimaryTemp_c( Brewtarget::tempQStringToSI(lineEdit_primaryTemp->text()) );
}

void RecipeExtrasWidget::updateSecondaryAge()
{
   if( recipe == 0 )
      return;

   if ( lineEdit_secAge->isModified() )
      recipe->setSecondaryAge_days( lineEdit_secAge->text().toDouble() );
}

void RecipeExtrasWidget::updateSecondaryTemp()
{
   if( recipe == 0 )
      return;

   if ( lineEdit_secTemp->isModified() )
      recipe->setSecondaryTemp_c( Brewtarget::tempQStringToSI(lineEdit_secTemp->text()) );
}

void RecipeExtrasWidget::updateTertiaryAge()
{
   if( recipe == 0 )
      return;

   if ( lineEdit_tertAge->isModified() )
      recipe->setTertiaryAge_days( lineEdit_tertAge->text().toDouble() );
}

void RecipeExtrasWidget::updateTertiaryTemp()
{
   if( recipe == 0 )
      return;

   if ( lineEdit_tertTemp->isModified() )
      recipe->setTertiaryTemp_c( Brewtarget::tempQStringToSI( lineEdit_tertTemp->text() ) );
}

void RecipeExtrasWidget::updateAge()
{
   if( recipe == 0 )
      return;

   if ( lineEdit_age->isModified() )
      recipe->setAge_days( lineEdit_age->text().toDouble() );
}

void RecipeExtrasWidget::updateAgeTemp()
{
   if( recipe == 0 )
      return;

   if ( lineEdit_ageTemp->isModified() )
      recipe->setAgeTemp_c( Brewtarget::tempQStringToSI( lineEdit_ageTemp->text() ) );
}

void RecipeExtrasWidget::updateDate(const QDate& date)
{
   if( recipe == 0 )
      return;

   if ( date.isNull()  ) 
      recipe->setDate( dateEdit_date->date() );
   else
      recipe->setDate( date );
}

void RecipeExtrasWidget::updateCarbonation()
{
   if( recipe == 0 )
      return;

   if ( lineEdit_carbVols->isModified() )
      recipe->setCarbonation_vols( lineEdit_carbVols->text().toDouble() );
}

void RecipeExtrasWidget::updateTasteNotes()
{
   if( recipe == 0 )
      return;

   recipe->setTasteNotes( btTextEdit_tasteNotes->toPlainText() );
}

void RecipeExtrasWidget::updateNotes()
{
   if( recipe == 0 )
      return;

   recipe->setNotes( btTextEdit_notes->toPlainText() );
}

void RecipeExtrasWidget::changed(QMetaProperty prop, QVariant /*val*/)
{
   if( sender() != recipe )
      return;

   showChanges(&prop);
}

void RecipeExtrasWidget::saveAll()
{
   //recObs->disableNotification();

   updateBrewer();
   updateBrewerAsst();
   updateTasteRating();
   updatePrimaryAge();
   updatePrimaryTemp();
   updateSecondaryAge();
   updateSecondaryTemp();
   updateTertiaryAge();
   updateTertiaryTemp();
   updateAge();
   updateAgeTemp();
   updateDate();
   updateCarbonation();
   updateTasteNotes();
   updateNotes();

   //recObs->reenableNotification();
   //recObs->forceNotify();

   hide();
}

void RecipeExtrasWidget::showChanges(QMetaProperty* prop)
{
   bool updateAll = (prop == 0);
   QString propName;
   QVariant val;
   if( prop )
   {
      propName = prop->name();
      val = prop->read(recipe);
   }
   
   if( ! recipe )
      return;
 
   // Unlike other editors, this one needs to read from recipe when it gets an
   // updateAll
   if ( updateAll )
   {
      lineEdit_age->setText(         Brewtarget::displayAmount(recipe->age_days(),          Units::days)    );
      lineEdit_ageTemp->setText(     Brewtarget::displayAmount(recipe->ageTemp_c(),         Units::celsius) );
      lineEdit_asstBrewer->setText(                            recipe->asstBrewer()                         );
      lineEdit_brewer->setText(                                recipe->brewer()                             );
      lineEdit_carbVols->setText(    Brewtarget::displayAmount(recipe->carbonation_vols())                  );
      lineEdit_primaryAge->setText(  Brewtarget::displayAmount(recipe->primaryAge_days(),   Units::days)    );
      lineEdit_primaryTemp->setText( Brewtarget::displayAmount(recipe->primaryTemp_c(),     Units::celsius) );
      lineEdit_secAge->setText(      Brewtarget::displayAmount(recipe->secondaryAge_days(), Units::days)    );
      lineEdit_secTemp->setText(     Brewtarget::displayAmount(recipe->secondaryTemp_c(),   Units::celsius) );
      lineEdit_tertAge->setText(     Brewtarget::displayAmount(recipe->tertiaryAge_days(),  Units::days)    );
      lineEdit_tertTemp->setText(    Brewtarget::displayAmount(recipe->tertiaryTemp_c(),    Units::celsius) );
      spinBox_tasteRating->setValue(                     (int)(recipe->tasteRating())                       );
      dateEdit_date->setDate(                                  recipe->date()                               );
      btTextEdit_notes->setPlainText(                          recipe->notes()                              );
      btTextEdit_tasteNotes->setPlainText(                     recipe->tasteNotes()                         );
   }
   else if( propName == "age_days" )
      lineEdit_age->setText( Brewtarget::displayAmount(val.toDouble()) );
   else if( propName == "ageTemp_c" )
      lineEdit_ageTemp->setText( Brewtarget::displayAmount(val.toDouble(), Units::celsius) );
   else if( propName == "asstBrewer" )
      lineEdit_asstBrewer->setText( val.toString() );
   else if( propName == "brewer" )
      lineEdit_brewer->setText( val.toString() );
   else if( propName == "carbonation_vols" )
      lineEdit_carbVols->setText( Brewtarget::displayAmount(val.toDouble()) );
   else if( propName == "primaryAge_days" )
      lineEdit_primaryAge->setText( Brewtarget::displayAmount(val.toDouble()) );
   else if( propName == "primaryTemp_c" )
      lineEdit_primaryTemp->setText( Brewtarget::displayAmount(val.toDouble(), Units::celsius) );
   else if( propName == "secondaryAge_days" )
      lineEdit_secAge->setText( Brewtarget::displayAmount(val.toDouble()) );
   else if( propName == "secondaryTemp_c" )
      lineEdit_secTemp->setText( Brewtarget::displayAmount(val.toDouble(), Units::celsius) );
   else if( propName == "tertiaryAge_days" )
      lineEdit_tertAge->setText( Brewtarget::displayAmount(val.toDouble()) );
   else if( propName == "tertiaryTemp_c" )
      lineEdit_tertTemp->setText( Brewtarget::displayAmount(val.toDouble(), Units::celsius) );
   else if( propName == "tasteRating" )
      spinBox_tasteRating->setValue( (int)(val.toDouble()) );
   else if( propName == "date" )
      dateEdit_date->setDate( val.toDate() );
   else if( propName == "notes" )
      btTextEdit_notes->setPlainText( val.toString() );
   else if( propName == "tasteNotes" )
      btTextEdit_tasteNotes->setPlainText( val.toString() );

}
