(function(root, factory) {

if (typeof module === 'object' && module.exports) {
    // CommonJS-like environments that support module.exports, like Node.
    module.exports = factory(require('../ApiClient'), require('./InvocationContext'), require('../CommonUtil'), require('../ResponseWrapper'), require('./Base')
, require('../handlers/CreateRefundHandler')
, require('../handlers/GetRefundHandler'), require('../OrbipayApiError'));
  }
}(this, function(ApiClient, InvocationContext, CommonUtil, ResponseWrapper, Base, CreateRefundHandler, GetRefundHandler, OrbipayApiError) {
  'use strict';

    /**
    * The Refund wrapper module.
    * @module wrappers/Refund
    */
  var exports = function(id_refund) {
  	var _this = this;
        Base.call(_this);
  		_this['ID_REFUND'] = id_refund;
  };

      /**
      * Constructs a <code>Refund</code> from a plain JavaScript object, optionally creating a new instance.
      * Copies all relevant properties from <code>data</code> to <code>obj</code> if supplied or a new instance if not.
      * @param {Object} data The plain JavaScript object bearing properties of interest.
      * @param {module:wrappers/Refund} obj Optional instance to populate.
      * @return {module:wrappers/Refund} The populated <code>Refund</code> instance.
      */
  exports.constructFromObject = function (data, obj) {
        if (data) {
            obj = obj || new exports();
            if (data.hasOwnProperty('refund_reference')) {
                obj['refund_reference'] = data['refund_reference'];
            }
            if (data.hasOwnProperty('id')) {
                obj['id'] = data['id'];
            }
            if (data.hasOwnProperty('url')) {
                obj['url'] = data['url'];
            }
            if (data.hasOwnProperty('refund_type')) {
                obj['refund_type'] = data['refund_type'];
            }
            if (data.hasOwnProperty('refund_amount')) {
                obj['refund_amount'] = data['refund_amount'];
            }
            if (data.hasOwnProperty('fee_refund')) {
                var FeeRefund = require('./FeeRefund');
                obj['fee_refund'] = FeeRefund.constructFromObject(data['fee_refund']);
            }
            if (data.hasOwnProperty('status')) {
                obj['status'] = data['status'];
            }
            if (data.hasOwnProperty('confirmation_number')) {
                obj['confirmation_number'] = data['confirmation_number'];
            }
            if (data.hasOwnProperty('refund_date')) {
                obj['refund_date'] = data['refund_date'];
            }
            if (data.hasOwnProperty('refund_entry_date')) {
                obj['refund_entry_date'] = data['refund_entry_date'];
            }
            if (data.hasOwnProperty('expected_refund_settlement_date')) {
                obj['expected_refund_settlement_date'] = data['expected_refund_settlement_date'];
            }
            if (data.hasOwnProperty('custom_fields')) {
                obj['custom_fields'] = data['custom_fields'];
            }
            if (data.hasOwnProperty('comments')) {
                obj['comments'] = data['comments'];
            }
            if (data.hasOwnProperty('source_payment')) {
                var SourcePayment = require('./SourcePayment');
                obj['source_payment'] = SourcePayment.constructFromObject(data['source_payment']);
            }
            if (data.hasOwnProperty('payment_network_response')) {
                var PaymentNetworkResponse = require('./PaymentNetworkResponse');
                obj['payment_network_response'] = PaymentNetworkResponse.constructFromObject(data['payment_network_response']);
            }
            if (data.hasOwnProperty('audit_info')) {
                var AuditInfo = require('./AuditInfo');
                obj['audit_info'] = AuditInfo.constructFromObject(data['audit_info']);
            }
            if (data.hasOwnProperty('ID_PAYMENT')) {
                obj['ID_PAYMENT'] = data['ID_PAYMENT'];
            }
            if (data.hasOwnProperty('ID_CUSTOMER')) {
                obj['ID_CUSTOMER'] = data['ID_CUSTOMER'];
            }
            if (data.hasOwnProperty('ID_REFUND')) {
                obj['ID_REFUND'] = data['ID_REFUND'];
            }
        }
        return obj;
  };


  exports.prototype = Object.create(Base.prototype);
  exports.prototype.constructor = exports;

    /**
    * The unique identifier in the client system for the refund.
    * @member {String} refund_reference
    */
  exports.prototype['refund_reference'] = undefined;
    /**
    * The unique identifier assigned by EBPP to the refund.
    * @member {String} id
    */
  exports.prototype['id'] = undefined;
    /**
    * This URL fetches the details of refund.
    * @member {String} url
    */
  exports.prototype['url'] = undefined;
    /**
    * The portion of the payment amount that is to be or has been refunded. The original payment can be refunded fully including the amount and the fee components, or partially, for just the amount or the fee component. Refund can also be initiated for an arbitrary amount limited by the original payment amount.
    * @member {String} refund_type
    */
  exports.prototype['refund_type'] = undefined;
    /**
    * The refund amount upto 2 decimal places.
    * @member {String} refund_amount
    */
  exports.prototype['refund_amount'] = undefined;
    /**
    * @member {FeeRefund} fee_refund
    */
  exports.prototype['fee_refund'] = undefined;
    /**
    * The status of the refund.
    * @member {String} status
    */
  exports.prototype['status'] = undefined;
    /**
    * The confirmation number or reference provided to the customer for the refund.
    * @member {String} confirmation_number
    */
  exports.prototype['confirmation_number'] = undefined;
    /**
    * The date on which the refund is scheduled to be made. It must be in ISO8601 full-date format, namely, YYYY-MM-DD.
    * @member {String} refund_date
    */
  exports.prototype['refund_date'] = undefined;
    /**
    * The date on which the refund captured in EBPP. It must be in ISO8601 full-date format, namely, YYYY-MM-DD.
    * @member {String} refund_entry_date
    */
  exports.prototype['refund_entry_date'] = undefined;
    /**
    * The date by which the credits would be posted to the original funding account. ISO8601 full-date format, YYYY-MM-DD
    * @member {String} expected_refund_settlement_date
    */
  exports.prototype['expected_refund_settlement_date'] = undefined;
    /**
    * The additional information or meta-information that EBPP can accept, maintain and transmit back to the client. The custom fields need to be configured with EBPP before they can be accepted. EBPP would reject custom fields that are not pre-configured. Please contact <a href = \"mailto: support@billerpayments.com\">support@billerpayments.com</a> for more information on configuring and using custom fields.
    * @member {{String: String}} custom_fields
    */
  exports.prototype['custom_fields'] = undefined;
    /**
    * Comments that can be used to recollect the operation performed on the resource object. API clients need to ensure that no sensitive information is passed in the memo. Alacriti (EBPP) is not responsible for the security of any sensitive information that may be passed as part of the memo.
    * @member {String} comments
    */
  exports.prototype['comments'] = undefined;
    /**
    * @member {SourcePayment} source_payment
    */
  exports.prototype['source_payment'] = undefined;
    /**
    * @member {PaymentNetworkResponse} payment_network_response
    */
  exports.prototype['payment_network_response'] = undefined;
    /**
    * @member {AuditInfo} audit_info
    */
  exports.prototype['audit_info'] = undefined;
    /**
    * The unique identifier assigned by EBPP to the payment.
    * @member {String} ID_PAYMENT
    */
  exports.prototype['ID_PAYMENT'] = undefined;
    /**
    * The unique identifier assigned by EBPP to the customer.
    * @member {String} ID_CUSTOMER
    */
  exports.prototype['ID_CUSTOMER'] = undefined;
    /**
    * The unique identifier assigned by EBPP to the refund.
    * @member {String} ID_REFUND
    */
  exports.prototype['ID_REFUND'] = undefined;

  /**
  * @param  {String} client_key - The client_key of Refund. 
  * @return {module:wrappers/Refund} The instance of <code>Refund</code>.
  */
  exports.prototype.forClient = function (client_key) {
        var _this = this;
	    Base.prototype.forClient.call(_this,client_key);
        return _this;
  };
  /**
  * @param  {String} channel - The channel of Refund. 
  * @return {module:wrappers/Refund} The instance of <code>Refund</code>.
  */
  exports.prototype.videChannel = function (channel) {
        var _this = this;
	    Base.prototype.videChannel.call(_this,channel);
        return _this;
  };
  /**
  * @param  {String} refund_amount - The refund_amount of Refund. 
  * @return {module:wrappers/Refund} The instance of <code>Refund</code>.
  */
  exports.prototype.withDetails = function (refund_amount) {
        var _this = this;

        _this['refund_amount'] = refund_amount;


        return _this;
  };
  /**
  * @param  {String} refund_reference - The refund_reference of Refund. 
  * @return {module:wrappers/Refund} The instance of <code>Refund</code>.
  */
  exports.prototype.withReference = function (refund_reference) {
        var _this = this;

        _this['refund_reference'] = refund_reference;


        return _this;
  };
  /**
  * @param  {String} comments - The comments of Refund. 
  * @return {module:wrappers/Refund} The instance of <code>Refund</code>.
  */
  exports.prototype.withMemo = function (comments) {
        var _this = this;

        _this['comments'] = comments;


        return _this;
  };
  /**
  * @param  {String} status - The status of Refund. 
  * @return {module:wrappers/Refund} The instance of <code>Refund</code>.
  */
  exports.prototype.withStatus = function (status) {
        var _this = this;

        _this['status'] = status;


        return _this;
  };
  /**
  * @param  {String} ID_CUSTOMER - The ID_CUSTOMER of Refund. 
  * @return {module:wrappers/Refund} The instance of <code>Refund</code>.
  */
  exports.prototype.forCustomer = function (id_customer) {
        var _this = this;

        _this['ID_CUSTOMER'] = id_customer;


        return _this;
  };
  /**
  * @param  {String} ID_PAYMENT - The ID_PAYMENT of Refund. 
  * @return {module:wrappers/Refund} The instance of <code>Refund</code>.
  */
  exports.prototype.forPayment = function (id_payment) {
        var _this = this;

        _this['ID_PAYMENT'] = id_payment;


        return _this;
  };
  /**
  * @param  {{String: String}} custom_fields - The custom_fields of Refund. 
  * @return {module:wrappers/Refund} The instance of <code>Refund</code>.
  */
  exports.prototype.withCustomFields = function (custom_fields) {
        var _this = this;

        _this['custom_fields'] = custom_fields;


        return _this;
  };
  /**
  * @param  {FeeRefund} fee_refund - The fee_refund of Refund. 
  * @return {module:wrappers/Refund} The instance of <code>Refund</code>.
  */
  exports.prototype.withFeeRefund = function (fee_refund) {
        var _this = this;

        _this['fee_refund'] = fee_refund;


        return _this;
  };

  exports.prototype.createdBy = function (requestor, requestor_type) {
        var _this = this;
        _this.requestedBy(requestor, requestor_type);
        return _this;
  };
  exports.prototype.retrievedBy = function (requestor, requestor_type) {
        var _this = this;
        _this.requestedBy(requestor, requestor_type);
        return _this;
  };

  exports.prototype.create = function (invocation_context, callback, live_mode, api_end_point) {
        var _this = this;
        var internalCallback = function (errorMessage, parsedData, httpResponse, exception) {
            try {
                var response = ResponseWrapper.wrapResponse(exports, exception, errorMessage, parsedData, httpResponse);
                if (callback) {
                    callback(response['exception'], response['data'])
                }
            } catch (e) {
                exception = OrbipayApiError.getDefaultException(e);
                if (callback) {
                    callback(exception)
                }
            }
        };
        try {
			_this.withContext(invocation_context, live_mode, api_end_point);
			var handler = new CreateRefundHandler();
			if (callback && CommonUtil.isFunction(callback)) {
			    return handler.process(_this, internalCallback);
			} else {
			    return handler.process(_this);
			}
		}
		catch (e){
		    var error = OrbipayApiError.getDefaultException(e);
		    if (callback) {
		        callback(error)
		    }
        }
  };
  exports.prototype.get = function (invocation_context, callback, live_mode, api_end_point) {
        var _this = this;
        var internalCallback = function (errorMessage, parsedData, httpResponse, exception) {
            try {
                var response = ResponseWrapper.wrapResponse(exports, exception, errorMessage, parsedData, httpResponse);
                if (callback) {
                    callback(response['exception'], response['data'])
                }
            } catch (e) {
                exception = OrbipayApiError.getDefaultException(e);
                if (callback) {
                    callback(exception)
                }
            }
        };
        try {
			_this.withContext(invocation_context, live_mode, api_end_point);
			var handler = new GetRefundHandler();
			if (callback && CommonUtil.isFunction(callback)) {
			    return handler.process(_this, internalCallback);
			} else {
			    return handler.process(_this);
			}
		}
		catch (e){
		    var error = OrbipayApiError.getDefaultException(e);
		    if (callback) {
		        callback(error)
		    }
        }
  };

  return exports;

}));