<?php
/*
 * This file is part of CiviCRM.
 *
 * CiviCRM 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.
 *
 * CiviCRM 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 CiviCRM.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Copyright (C) 2012
 * Licensed to CiviCRM under the GPL v3 or higher
 *
 * Modified by Lisa Marie Maginnis <lisa@fsf.org> (http://www.fsf.org)
 *
 */

class CRM_Core_Payment_trustcommerce_IPN extends CRM_Core_Payment_BaseIPN {
  function __construct() {
    parent::__construct();
  }


  function main($component = 'contribute') {
  static $no = NULL;
    $billingid = CRM_Utils_Request::retrieve('billingid', 'String', $no, FALSE, 'GET');
    $input['status'] = CRM_Utils_Request::retrieve('status', 'String', $no, FALSE, 'GET');
    $input['amount'] = CRM_Utils_Request::retrieve('amount', 'String', $no, FALSE, 'GET');
    $input['date'] = CRM_Utils_Request::retrieve('date', 'String', $no, FALSE, 'GET');
    $input['trxn_id'] = CRM_Utils_Request::retrieve('trxn_id', 'String', $no, FALSE, 'GET');
    $checksum = CRM_Utils_Request::retrieve('checksum', 'String', $no, FALSE, 'GET');

    if ($billingid) {
      if( $input['status'] == '' || $input['amount'] == '' || $input['date'] == '' || $input['trxn_id'] == '' || md5($billingid.$input['trxn_id'].$input['amount'].$input['date']) != $checksum) {
	 CRM_Core_Error::debug_log_message("Error: IPN called with out proper fields");
	 echo "Error: invalid paramaters<p>\n";
	 exit;
       }


       $ids = $objects = array();
       $input['component'] = $component;

       // load post ids in $ids
       $ids = NULL;
       $ids = $this->getIDs($billingid, $input, $input['component']);

       $ids['trxn_id'] = $input['trxn_id'];

       if($this->checkDuplicate($input, $ids) != NULL) {
	 CRM_Core_Error::debug_log_message("Success: This payment has already been processed.");
	 echo "Success: This payment has already been processed<p>\n";
	 exit;
       }
       var_dump($ids);
       var_dump($input);

       if(array_key_exists('membership', $ids)) {
	 $membership = array();
	 $params = array('id' => $ids['membership']);
	 $obj = CRM_Member_BAO_Membership::retrieve($params, $membership);
	 $objects['membership'] = array(&$obj);
       }
       var_dump($ids);
       var_dump($input);

      $paymentProcessorID = CRM_Core_DAO::getFieldValue('CRM_Financial_DAO_PaymentProcessorType',
							'TrustCommerce', 'id', 'name'
							);

      if (!$this->validateData($input, $ids, $objects, TRUE, $paymentProcessorID)) {
        return FALSE;
      }
      //     var_dump($objects);
      
      if ($component == 'contribute' && $ids['contributionRecur']) {
        // check if first contribution is completed, else complete first contribution
        $first = TRUE;
        if ($objects['contribution']->contribution_status_id == 1) {
          $first = FALSE;
        }

	
	return $this->processRecur($input, $ids, $objects, $first);
	
    }

  }
}

  protected function checkDuplicate($input, $ids) {
//    $sql='select id from civicrm_contribution where receive_date like \''.$input['date'].'%\' and total_amount='.$input['amount'].' and contact_id='.$ids['contact'].' and contribution_status_id =  1 limit 1';
    $sql="select id from civicrm_contribution where trxn_id = '".$ids['trxn_id']."'";


    $result = CRM_Core_DAO::executeQuery($sql);
    $result->fetch();
    $id = $result->id;
    return $id;
  }
  protected function processRecur($input, $ids, $objects, $first) {
    $recur = &$objects['contributionRecur'];
    $contributionStatus = CRM_Contribute_PseudoConstant::contributionStatus(NULL, 'name');

    $transaction = new CRM_Core_Transaction();

    $now = date('YmdHis');

    // fix dates that already exist
    $dates = array('create_date', 'start_date', 'end_date', 'cancel_date', 'modified_date');
    foreach ($dates as $name) {
      if ($recur->$name) {
        $recur->$name = CRM_Utils_Date::isoToMysql($recur->$name);
      }
    }

    if (!$first) {
      // create a contribution and then get it processed
      $contribution = new CRM_Contribute_BAO_Contribution();
      $contribution->contact_id = $ids['contact'];
      $contribution->financial_type_id  = $objects['contributionType']->id;
      $contribution->contribution_page_id = $ids['contributionPage'];
      $contribution->contribution_recur_id = $ids['contributionRecur'];
      $contribution->receive_date = $input['date'];
      $contribution->currency = $objects['contribution']->currency;
      $contribution->payment_instrument_id = 1;
      $contribution->amount_level = $objects['contribution']->amount_level;
      $contribution->address_id = $objects['contribution']->address_id;
      $contribution->honor_contact_id = $objects['contribution']->honor_contact_id;
      $contribution->honor_type_id = $objects['contribution']->honor_type_id;
      $contribution->campaign_id = $objects['contribution']->campaign_id;
      $contribution->total_amount = $input['amount']; 

      $objects['contribution'] = &$contribution;
    }
    $objects['contribution']->invoice_id = md5(uniqid(rand(), TRUE));
    //    $objects['contribution']->total_amount = $objects['contribution']->total_amount;
    $objects['contribution']->trxn_id = $input['trxn_id'];

    // check if contribution is already completed, if so we ignore this ipn
    if ($objects['contribution']->contribution_status_id == 1) {
      $transaction->commit();
      CRM_Core_Error::debug_log_message("returning since contribution has already been handled");
      echo 'Success: Contribution has already been handled<p>';
      echo '';
      return TRUE;
    }

    $sendNotification = FALSE;
    if ($input['status'] == 1) {

      // Approved
      if ($first) {
        $recur->start_date = $now;
        $sendNotification = TRUE;
        $subscriptionPaymentStatus = CRM_Core_Payment::RECURRING_PAYMENT_START;
      }
      $statusName = 'In Progress';
      if (($recur->installments > 0) &&
	  ($input['subscription_paynum'] >= $recur->installments)
	  ) {
        // this is the last payment
        $statusName = 'Completed';
        $recur->end_date = $now;

        $sendNotification = TRUE;
        $subscriptionPaymentStatus = CRM_Core_Payment::RECURRING_PAYMENT_END;
      }
      $recur->trxn_id = $input['trxn_id'];
      $recur->total_amount = $input['amount'];
      $recur->payment_instrument_id = 1;
      $recur->fee = 0;
      $recur->net_amount = $input['amount'];

      $recur->modified_date = $now;
      $recur->contribution_status_id = array_search($statusName, $contributionStatus);
      $recur->save();
    }
    else {
      // Declined
      // failed status

      $recur->trxn_id = $input['trxn_id'];
      $recur->total_amount = $input['amount'];
      $recur->payment_instrument_id = 1;
      $recur->fee = 0;
      $recur->net_amount = $input['amount'];

      $recur->contribution_status_id = array_search('Failed', $contributionStatus);
      $recur->cancel_date = $now;
      $recur->save();

      CRM_Core_Error::debug_log_message("Subscription payment failed");

      $input['skipComponentSync'] = TRUE;
      $this->failed($objects, $transaction, $input);
    }

    $input['is_test'] = 0;

    $this->completeTransaction($input, $ids, $objects, $transaction, $recur);

      echo 'Success: Created new contribution: '.$ids['contribution'].' for cid: '.$ids['contact'].'\n';
      CRM_Core_Error::debug_log_message('Success: Created new contribution: '.$ids['contribution'].' for cid: '.$ids['contact']);

    if ($sendNotification) {
      $autoRenewMembership = FALSE;
      if ($recur->id &&
	  isset($ids['membership']) && $ids['membership']
	  ) {
        $autoRenewMembership = TRUE;
      }




      //send recurring Notification email for user
      CRM_Contribute_BAO_ContributionPage::recurringNotify($subscriptionPaymentStatus,
							   $ids['contact'],
							   $ids['contributionPage'],
							   $recur,
							   $autoRenewMembership
							   );




    }



  }

 protected function getIDs($billingid, $input, $module) {
    $sql = "SELECT cr.id, cr.contact_id, co.id as coid
    	       FROM civicrm_contribution_recur cr
	       INNER JOIN civicrm_contribution co ON co.contribution_recur_id = cr.id
   	       WHERE cr.processor_id = '$billingid' LIMIT 1";


    $result = CRM_Core_DAO::executeQuery($sql);
    $result->fetch();
    $ids['contribution'] = $result->coid;
    $ids['contributionRecur'] = $result->id;
    $ids['contact'] = $result->contact_id;

    if (!$ids['contributionRecur']) {
      CRM_Core_Error::debug_log_message("Could not find billingid: ".$billingid);
      echo "Failure: Could not find contributionRecur<p>\n";
      exit();
    }

    // get page id based on contribution id
    $ids['contributionPage'] = CRM_Core_DAO::getFieldValue('CRM_Contribute_DAO_Contribution',
      $ids['contribution'],
      'contribution_page_id'
    );

    if ($module == 'event') {
      // FIXME: figure out fields for event
    }
    else {
      // get the optional ids

      // Get membershipId. Join with membership payment table for additional checks
      $sql = "
    SELECT m.id
      FROM civicrm_membership as m
     WHERE m.contribution_recur_id = '{$ids['contributionRecur']}'
     LIMIT 1";
      if ($membershipId = CRM_Core_DAO::singleValueQuery($sql)) {

	$ids['membership'] = $membershipId;
      }
      
    }

  return $ids;
}



}
