/**
 * Namespace for the ATT Provider class
 */
Sencha = {};

/**
 * @class Sencha.Provider
 * Sencha.Provider exposes methods to access the ATT API.  
 * When a method is called on the client a request is made to the server. 
 * The server will validate the request and then make the appropriate call
 * to the ATT api.
 *
All code examples were taken form the Kitchen Sink application.


Init
----

From client/app/app.js

    this.provider = new Sencha.Provider();

Authentication
---

The SDK supports three forms of authentication. Login and Automatic and Payment.  Depending on the API call you will need one form other the other.
SMS, MMS and WAPPush allow the developer to send messages using the Client Credential or Autonmous Client model for oauth.


TODO this section will need to be rewritten when the OAUTH 2.0 code is part of the SDK.

Automatic (OAuth Model - Client Credential)
----

When using the SDK when you attempt to send call one of these methods the server will request an authorization token from ATT using your application credentials. 
And then make the API call automatically.  The user of the application will not need to explicitly authorize the action and you can send messages to any valid 
ATT MSISDN.

 
Login  (OAuth Model - Authorization Code)
----
For the Device Location and Device Info API calls you will need explicit permission from the user to access information about their device. 
The SDK provides api calls to check to see if the user is currently authorized and if not the API will create an iframe and redirect the user to the OAUTH login sequence.  
When the user returns from OAUTH the user will have a valid access token associated with their session.



      // authScope ='TL,DC,WAP,SMS,MMS,PAYMENT';
      var this = self;
      
      
      // isAuthorize checks to see if the user has a valid auth token stored on the SDK server
      // If the user has a valid token we don't need to ask the user to re-authorize. 
      
      KitchenSink.provider.isAuthorized(self.authScope, {
  
         success: function() {
              // On successful authorisation, proceed to the next page
              // KitchenSink specific code to display the API list. 
              // Place application specific code here.
              self.add({xtype: 'attApiList'});
              self.setActiveItem(1, false);
              self.remove(0);
              KitchenSink.provider.removeIframe();
          },
          failure: function() {
              // We don't have a valid token on the SDK server.
              // Ask the user to login and authorize this application to process payments.
              // This will pop up an AT&T login followed by an authorisation screen.
              KitchenSink.provider.authorizeApp(self.authScope, {
                  success: function() {
                      // On successful authorisation, proceed to the next page

                      console.log("arguments", arguments);
                      self.add({xtype: 'attApiList'});
                      self.setActiveItem(1, false);
                      self.remove(0);
                      
                      
                      KitchenSink.provider.removeIframe();
                  },
                  failure: function() {
                    console.log("failure arguments", arguments);
                      KitchenSink.provider.removeIframe();
                  }
              });
      
          }
  
  
      })

Payment
---
 
 TODO this section will need to be written when the Payment 2.0 code is part of the SDK.

Making API Calls
---

Call the provder API method with the required parameters.
On success you will recieve a JSON encoded response from the server.
This data is idential to the data returned by the APIs from ATT.

      KitchenSink.provider.sendSms('SOMEPHONENUMBER', 'your sms message', {
          success: function(response) {
              self.setLoading(false);
              KitchenSink.showResults(response, "SMS Sent");
       

              self.smsId = response.Id;
              Ext.getCmp('sms-status-button').enable();
          },
          failure: function(error) {
            console.log("failure", error);
              self.setLoading(false);
              Ext.Msg.alert('Error', error);
          }
      });

 
Error Handling
----

the callback data should be checked for two error keys: apiError and error

- apiError -- this key contains the raw JSON encoded error from the ATT API call. 
- error -- this key will be present in the event of an error generated by the SDK server code. 
 
 *
 * @singleton
 */
Sencha.Provider = function(){
    Ext.Direct.addProvider({
        "type":"remoting",       // create a Ext.direct.RemotingProvider
        "url": attApiBasePath + "/direct_router", // url to connect to the Ext.Direct server-side router.
        "actions":{              // each property within the actions object represents a Class
            "Provider": [        // array of methods within each server side Class
                /**
                 * Given a scope, return the corresponding AT&T oAuth URL
                 * @param {String} scope a comma separated list of services that teh app requires access to
                 * @method oauthUrl
                 */
                {
                    "name": "oauthUrl", // name of method
                    "len": 1
                },
                /**
                 * Return information on a device
                 * @param {String} tel MSISDN of the device to query
                 * @param {Function} success successful callback function 
                 * @param {Function} fail  failure callback function
                 * @method deviceInfo
                 */
                {
                    "name": "deviceInfo",
                    "len": 1
                },
                /**
                 * Return location info for a device
                 * @param {String} tel MSISDN of the device to query
                 * @param {Number} accuracy Accuracy of the location call
                 * @param {Function} success successful callback function 
                 * @param {Function} fail  failure callback function
                 * @method deviceLocation
                 */
                {
                    "name": "deviceLocation",
                    "len": 2
                },
                /**
                 * Sends an SMS to a recipient
                 * @param {String} tel The MSISDN of the recipient(s). Can contain comma separated list for multiple recipients.
                 * @param {String} message The text of the message to send
                  * @param {Function} success successful callback function 
                  * @param {Function} fail  failure callback function
                 * @method sendSms
                 */
                {
                    "name": "sendSms",
                    "len": 2
                },
                
                /**
                 * Check the status of a sent SMS
                 * @param {String} sms_id The unique SMS ID as retrieved from the response of the sendSms method
                  * @param {Function} success successful callback function 
                  * @param {Function} fail  failure callback function
                 * @method smsStatus
                 */
                {
                    "name": "smsStatus",
                    "len": 1
                },
                /**
                 * Retrieves a list of SMSes sent to the application's short code
                  * @param {Function} success successful callback function 
                  * @param {Function} fail  failure callback function
                 * @method receiveSms
                 */
                {
                    "name": "receiveSms",
                    "len": 0
                },
                /**
                 * Check the status of a sent SMS
                 * @param {String} mms_id The unique MMS ID as retrieved from the response of the sendMms method
                  * @param {Function} success successful callback function 
                  * @param {Function} fail  failure callback function
                 * @method mmsStatus
                 */
                {
                    "name": "mmsStatus",
                    "len": 1
                },
                
                /**
                 * Send a WAP Push message
                 * @param {String} tel The MSISDN of the recipient(s). Can contain comma separated list for multiple recipients.
                 * @param {String} message The XML document containing the message to be sent.     
                 * @param {Function} success successful callback function 
                 * @param {Function} fail  failure callback function
                 * @method wapPush
                 */
                {
                    "name": 'wapPush',
                    "len": 2
                },
                /**
                 * paymentStatus NOT IMPLEMENTED
                 * @method paymentStatus
                 */
                {
                    "name": 'paymentStatus',
                    "len": 1
                },
                /**
                 * subscriptionStatus NOT IMPLEMENTED
                 * @method subscriptionStatus
                 */
                {
                    "name": 'subscriptionStatus',
                    "len": 1
                }
                
            ]
        },
        "namespace":"Sencha"
    });

    var self = this;
    for(var method in Sencha.Provider) {
        if (Sencha.Provider.hasOwnProperty(method)) {
            (function() {
                var scopedMethod = method;
                self[scopedMethod] = function() {
                    var configObj = arguments[arguments.length - 1];
                    var selfArgs = Array.prototype.slice.call(arguments).slice(0, arguments.length - 1);
               
                    self.successCallback = configObj.success;
                    self.errorCallback = configObj.failure;
               
                    selfArgs.push(function(result, evt) {
                      
                        if(evt.status) {
                            configObj.success(result);
                        } else {
                            configObj.failure(evt.error);
                        }
                    });
                    
                    Sencha.Provider[scopedMethod].apply(Sencha.Provider[scopedMethod], selfArgs);
                }
            })();
        }
    }
};

Sencha.Provider.prototype = {

    /**
     * Checks to see if the app is authorised against the given scopes.
     * @param scope {String} Comma separated list of scopes the app requires access to.
     * @param options {Object} Must contain `success` and `failure` callbacks
     *
     */
    isAuthorized: function(scope, options) {

        this.successCallback = options.success;
        this.failureCallback = options.failure;

        var self = this;

        Ext.Ajax.request({
            url: '/auth/check?scope=' + scope,
            method: 'GET',
            success: function(response){
                var jsonResponse = JSON.parse(response.responseText)
                if (jsonResponse.authorized) {
                    self.successCallback();
                } else {
                    self.failureCallback();
                }
            }
        });
    },

    /**
     * Initiate client authorisation window for the user to authorise the application
     * against the given scopes.
     * @param options {Object} Must contain a `scope` parameter as well as `success` and `failure` callbacks
     */
    authorizeApp: function(scope, options) {

        this.successCallback = options.success;
        this.failureCallback = options.failure;

        var self = this;

        Sencha.Provider.oauthUrl(scope, function(result, e) {

           console.log("arguments", arguments);

            self.createIframe(result);
        });
    },

    /**
     * Takes the response JSON from a server side payment request and pops up
     * an authorisation window which the user must accept.
     * @param response {Object} Response object from payment action
     * @param options {Object} Must contain `success` and `failure` callbacks
     */
    authorizePayment: function(response, options) {
        this.successCallback = options.success;
        this.failureCallback = options.failure;

        var resp = JSON.parse(response.responseText);
        if (resp.error) {
            this.failureCallback(resp);
        } else {
            this.createIframe(resp.redirect);
        }
    },

    /**
     * @private
     * Creates an iframe on document.body (above the viewable app) and redirects
     * it to the given src URL
     * @param src {String} URL to redirect the iframe
     * @param options {Object} Options to set success and failure callbacks
     */
    createIframe: function(src, options) {

        this.redirect = src;

        if (options) {
            this.successCallback = options.success;
            this.failureCallback = options.failure;
        }

        var mask = document.createElement('div');
        mask.setAttribute('style', "position: absolute; top: 0; height: 600px; width: 100%; z-index: 900; border: 0; background: #fff;");
        mask.setAttribute('id', "providerMask");
        document.body.appendChild(mask);

        var iframe = document.createElement('iframe');
        iframe.src =  attApiBasePath + "/att_redirect";
        iframe.setAttribute('style', "position: absolute; top: 0; height: 600px; width: 100%; z-index: 1000; border: 0;");
        iframe.setAttribute('id', "providerIframe");
        document.body.appendChild(iframe);
    },

    /**
     * @private
     * Removed the iframe overlay and mask from the screen
     */
    removeIframe: function() {
        var iframe = Ext.get('providerIframe'),
            mask = Ext.get('providerMask');

        if (iframe) iframe.remove();
        if (mask) mask.remove();
    }
}
