/*
 this library is designed to receive,
 maintain and transfer a punchout session
 through punchout2go.
 */

var po2goExt_enabled = true; //False if you don't have the file.

/**
 * used to test we can access the cookies.
 * @return bool
 */
function cookieTest ()
{
    document.cookie = "__test";
    if (document.cookie.length >= 1 &&
        document.cookie.indexOf("__test") > -1){
        return true;
    }
    return false;
}

/**
 * Po2go object.
 * Must be initialized.
 *
 * @param p
 * @constructor
 */
var Po2go = function (p) {

    // extension object for customizations
    this.extension = p.extension ? p.extension : 0;

    // default po2go connection information
    this.gateway = p.gateway ? p.gateway : 'connect.punchout2go.com';
    if (p.secure !== undefined) {
        this.secure = p.secure;
    } else this.secure = 1;
    this.transfer_url = p.transfer_url ? p.transfer_url : '/gateway/link/punchin/id/';

    this.return_url = p.return_url ? p.return_url : '';

    // catalog/session options
    this.account = p.account ? p.account : ''; // customer apikey
    this.catalog = p.catalog ? p.catalog : ''; // catalog key
    this.session_id = p.session_id ? p.session_id : ''; // current session id

    // use control options
    this.punchout_only = parseInt(p.punchout_only ? p.punchout_only : 0);
    this.punchout_only_text = p.punchout_only_text ? p.punchout_only_text : 'This site must be accessed through a valid PunchOut Session.';
    this.skip_cookie_test = p.skip_cookie_test ? p.skip_cookie_test : true; // set to false to ALWAYS require cookies regardless of punchout.
    this.default_unspsc = p.default_unspsc ? p.default_unspsc : '';
    this.default_uom = p.default_uom ? p.default_uom : '';

    // session cookie options?
    this.cookie_lifetime = p.cookie_lifetime ? p.cookie_lifetime : 0; // session
    this.cookie_domain = p.cookie_domain ? p.cookie_domain : ''; // uses current
    this.cookie_path = p.cookie_path ? p.cookie_path : '/';
    this.cookie_name = p.cookie_name ? p.cookie_name : 'pos_id';
    this.query_param = p.query_param ? p.query_param : 'pos_id';
    this.cookie_message = p.cookie_message ? p.cookie_message : 'Cookies must be permitted to access this website.<br>In order to allow cookies, please <a id="cookieLaunch">Click Here</a>.';
    this.cookie_message_ie = p.cookie_message_ie ? p.cookie_message_ie : 'Cookies are required to maintain your session. You many need to set this site as a TRUSTED SITE. If you would like to view this site in a new window, please <a id="cookieLaunch">Click Here</a>.';

 	this.logging = p.logging ? p.logging : 0;
 	this.confirm_transfer = p.confirm_transfer ? p.confirm_transfer : 0;

    // the cart.
    this.cart = {
        // standard data
        edit_mode:0,
        total:0,
        currency:'USD',
        // items
        items:[],
        // other non-standard values
        discount:0,
        discount_title:'',
        shipping:0,
        shipping_method:'',
        tax:0,
        tax_description:''
    };

}

/**
 *  This is a prototype for the Po2go object. It contains static information (e.g., methods).
 */
Po2go.prototype = {

    /**
     * identifies the how the Po2go object is loaded
     * 0 = not a punchout
     * 1 = punchout ready
     * 2 = remote start
     * -1 = punchout only locked
     * -2 = cookies blocked
     */
    status : 0,

    // start up stuff to be run every time a page loads.
    init : function ()
    {

        // check for a cookie setup instruction. if true, break out of init.
        // cookie setup is done in front of any other logic.
        if (this.checkCookieSetup()) {
            return;
        }

        // run the preInit
        this._preInit();

        // cookies are required. check before bothering with anything else.
        if (this.skip_cookie_test == true
                || cookieTest()) {
            // load the session
            if (this.loadSession()) {
 				this.status = 1;
            } else {
                // punchout session is not loaded.
                if (this.punchout_only) {
                    // lock out the session
                    this.punchoutOnlyLockout(); //Redirect somewhere.
                    this.status = -1;
                    this._cleanUp(); // cleanup anything that might be left over.
                }
            }
        } else {
            // this means cookies are not working
            this.cookieMessage();
            this.status = -2;
        }

        this._postInit();
    },

    // remote start..
    startSession : function ()
    {

        this._postInit();
    },

    /**
     * checks for cookie setup param and launches
     * extra setup modals. possibly no longer used.
     *
     * @return {Boolean}
     */
    checkCookieSetup : function ()
    {
        var csetup = jQuery.url().param('csetup');
        if (typeof csetup == 'string'
            && csetup != '') {
            this.status = -2;
            switch (csetup) {
                case "step1" :
                    this.cookieSetup1();
                    return true;
                case "step2" :
                    this.cookieSetup2();
                    return true;
            }
        }
        return false;
    },

    /**
     * test for extension object and method within that object
     *
     * @param method
     * @return {Boolean}
     */
    hasExtension : function (method)
    {
        if (typeof this.extension == 'object') {
            if (typeof this.extension[method] == 'function') {
                return true;
            }
        }
        return false;
    },

    /**
     * called before init begins
     *
     * @private
     */
    _preInit : function ()
    {
        if (this.hasExtension('_preInit')) {
            this.extension._preInit(this);
        }
    },

    /**
     * called after init has completed
     *
     * @private
     */
    _postInit : function ()
    {
        if (this.hasExtension('_postInit')) {
            this.extension._postInit(this);
        }
        if (this.status == 1) {
            jQuery('body').addClass('punchout');
        }
    },

    /**
     * called when closing transferring or navigating away
     * clean up must return TRUE to automatically transfer.
     * return false if you need to wait for something else
     * to happen then trigger transfer manually.
     *
     * @return {*}
     * @private
     */
    _cleanUp : function ()
    {
		this.log('_cleanUp()');
        if (this.hasExtension('_cleanUp')) {
			this.log('extension._cleanUp()');
            if (!this.extension._cleanUp(this)) {
            	return false;
            }
        }
		this.deleteCookie(this.cookie_name);
		this.deleteCookie('return_url');
        return true;
    },


    /**
     *  Load the session. First check the query string for the pos_id,
     *  if not found, check the cookie.
     * @returns {boolean} True if successful, False if this.cookie_name fails to be found
     */
    loadSession : function ()
    {
        if (!this.session_id) {
            //Check the query string
            var session_id = jQuery.url().param(this.query_param);
            var return_url = jQuery.url().param('return_url');

            if (!session_id) {
                //Not in query string. Check the cookie.
                session_id = this.getCookie(this.cookie_name);
                return_url = this.getCookie('return_url');
            }

            if (session_id){
                //Found it somewhere. Save it.
                this.setSessionId(session_id);
                if (return_url) this.setReturnUrl(return_url);
                return true;
            }

            //Never found it.
            return false;
        }
        return true;
    },

    /**
     * validates that the session cookie is readable.
     * if it is not, then we probably are unable to read cookies
     *
     * @return {Boolean}
     */
    checkSession : function ()
    {
        return (this.getCookie(this.cookie_name) == this.session_id);
    },

    /**
     * Set the session attribute, then set the cookie.
     *
     * @param session_id
     */
    setSessionId : function (session_id)
    {
        this.session_id = session_id;
        this.setCookie(this.cookie_name, this.session_id);
    },

    /**
     * Set the session attribute, then set the cookie.
     *
     * @param session_id
     */
    setReturnUrl : function (return_url)
    {
        this.return_url = return_url;
        this.setCookie('return_url', this.return_url);
    },

    /**
     * Add an Item to the Cart
     * @param item - an array, defined as:

              item {
                "quantity":             "" ,
                "supplierid":           "",
                "supplierauxid":        "",
                "unitprice":            "",
                "totalprice":           "",
                "currency":             "USD",
                "description":          "",             //The name
                "language":             "en",
                "classification":       "",
                "classdomain":          "",
                "uom":                  "EA",

              //Non-Standard
                discount_percent:       0,
                total_discount_amount:  0,
                tax_percent:            0,
                total_tax_amount:       0
            }
    **/
    addItemToCart : function (item)
    {
        // price format clean up done with _prepare
        // maybe some login with default values
        // not entirely sure this is legit.
        this.cart.items[this.cart.items.length] = item;
    },

    addItemsToCart : function(items)
    {
        jQuery(items).each(function (index,item) {
            POSession.addItemToCart(item);
        });
    },

    collectAndTransfer : function (selector)
    {
    	Basic.Modal.show('Collecting items..');

    	jQuery(selector).each(jQuery.proxy(this.collectItem,this));

    	if (this.cart.items.length == 0) {
    		Basic.Modal.show('no items were added.');
    		return;
    	}
    	return this.transferCart();
    },

    collectItem  : function (idx,elm) {
  		var data_string = jQuery(elm).html();
  		var item = eval('('+ data_string +')');
  		this.addItemToCart(item);
    },

    // external submit use
    transferCart : function ()
    {
    	this.log('transferCart()');
        Basic.Modal.show('Preparing transfer..');
        // somebody could override this to inject some
        // additional logic.
        //for(var i = 0; i < this.cart.items.length; i++){
        //    var fixed = this.cart.items[i].totalprice.replace(",", ""); //USD only
        //    this.cart.total += Number(fixed);
        //}
        this._prepareCart();
        // run clean up.
        if (this._cleanUp()) {
            this._transferCart(); // transfer will cause the browser to navigate aways.
        }
    },

    /**
     * cancels the current punchout session; redirects/returns user to to the return_url
     * @return {*}
     */
    cancel : function ()
    {
      var returnURL = this.getTransferAction() + "?redirect=1";
      window.location = returnURL;
    },

    /**
     * normalize and prepare cart data.
     *
     * @private
     */
    _prepareCart : function ()
    {
    	this.log('_prepareCart()');
        this.cart.tax = this._cleanPrice(this.cart.tax);
        this.cart.discount = this._cleanPrice(this.cart.discount);
        this.cart.shipping = this._cleanPrice(this.cart.shipping);
        this.cart.total = this._cleanPrice(this.cart.total);

        for(var i = 0; i < this.cart.items.length; i++){
            this.cart.items[i].unitprice = this._cleanPrice(this.cart.items[i].unitprice);
            this.cart.items[i].totalprice = this._cleanPrice(this.cart.items[i].totalprice);
            this.cart.items[i].total_discount_amount = this._cleanPrice(this.cart.items[i].total_discount_amount);
            this.cart.items[i].total_tax_amount = this._cleanPrice(this.cart.items[i].total_tax_amount);
            this.cart.items[i].description = this._cleanDescription(this.cart.items[i].description);
        }
    },

    /**
     * clean description string, removes HTML entity encoding
     *
     * @param description
     * @return {*}
     * @private
     */
    _cleanDescription : function(description){

      var tmpTextArea = document.createElement("textarea");
      tmpTextArea.innerHTML = description;
      return tmpTextArea.value;
    },
    /**
     * clean price string
     *
     * @param price
     * @return {*}
     * @private
     */
    _cleanPrice : function (price)
    {
       if (typeof(price) === "string") {
        price = price.replace("$", ""); // remove any currency ids
        price = price.replace(",", ""); // remove "," from price string - not currency safe.
       }
        // price = price.replace(',',"");
        return price;
    },


    /**
     * actual building of the cart form and transferring the data.
     *
     * @private
     */
    _transferCart : function ()
    {
    	this.log('_transferCart()');
        if (self.name == 'external_punchout'
            && window.opener) {
            window.opener.jQuery('body').append("<form action='"+ this.getTransferAction() +"' method=POST id='transferCartForm'></form>");
            window.opener.jQuery('#transferCartForm').append("<input type='hidden' name='apikey' value='"+ this.account +"' />");
            window.opener.jQuery('#transferCartForm').append("<input type='hidden' name='version' value='1.0' />");
            window.opener.jQuery('#transferCartForm').append("<input type='hidden' name='params' value='"+ this.getSerializedCart() +"' />");
            window.opener.jQuery('#transferCartForm').submit();
            self.close();
        } else {
	    	this.log('standard output.');
            jQuery('body').append("<form action='"+ this.getTransferAction() +"' method=POST id='transferCartForm'></form>");
            jQuery('#transferCartForm').append("<input type='hidden' name='apikey' value='"+ this.account +"' />");
            jQuery('#transferCartForm').append("<input type='hidden' name='version' value='1.0' />");
            jQuery('#transferCartForm').append("<input type='hidden' name='params' value='"+ this.getSerializedCart() +"' />");
	    	this.log('form completed.');
	    	if (this.confirm_transfer) {
	    		if (self.confirm(this.confirm_transfer)) {
		            jQuery('#transferCartForm').submit();
	    		} else {
		            jQuery('#transferCartForm').append("<input type='submit' name='submit' value='Transfer Items' />");
	    		}
	    	} else {
	            jQuery('#transferCartForm').submit();
	    	}
        }
    },

    /**
     * get the required serialized cart
     *
     * @return {*}
     */
    getSerializedCart : function ()
    {
		this.log('getSerializedCart()');
        var cartString = '{"body":'+ this.getCartAsJson() +'}';
        cartString = cartString.replace("$", "");
		this.log('string // pre-b64 '+ cartString);
        return Base64.encode(cartString);
     },

    /**
     * get the json string
     *
     * @return {*}
     */
    getCartAsJson : function ()
    {
        return JSON.stringify(this.cart);
    },

    /**
     * get the url where orders should be sent back to
     *
     * @return {String}
     */
    getTransferAction : function ()
    {
        var returnURL = (this.secure ? 'https://' : 'http://') + this.gateway + this.transfer_url + this.session_id;
        if (this.return_url != '') {
          //return this.return_url;
          returnURL = this.return_url;
        }
        //return (this.secure ? 'https://' : 'http://') + this.gateway + this.transfer_url + this.session_id;
        return returnURL;
    },



    /**
     *
     * @return {*}
     */
    getInstance : function()
    {
        return this;
    },

    /**
     * basic debugging info sent out to a log screen
     */
    debug : function ()
    {
    	if (this.logging == 0) {
	    	this.logging = 1; // turn logging on
    	}

        this.log('Session ID :'+ this.session_id);
        this.log('Account : '+ this.account);
        this.log('Catalog : '+ this.catalog);
        this.log('POST : '+ this.getTransferAction());
        this.log('Cart : '+ this.getCartAsJson());
    },

    /**
     * write out to a log screen.
     *
     * @param line
     */
    log : function (line)
    {
    	if (this.logging != 0) {
    		if (this.logging == 'console') {
    			if (console) {
    				console.log(line);
    			}
    		} else {
				if (jQuery('#logwindow').length == 0) {
					jQuery('body').append('<div id="logwindow" style="top:0px;left:0px;position:absolute;width:20px;height:20px;overflow:hidden;border:1px solid black;background-color:gray;color:#adff2f;padding:10px;line-height:1.2;font-family:courier;font-size:10px;z-index:99999999"></div>');
					jQuery('#logwindow').bind('click',function () {
						if (jQuery('#logwindow').hasClass('open')) {
							jQuery('#logwindow').width(20);
							jQuery('#logwindow').height(20);
							jQuery('#logwindow').css('overflow','hidden');
							jQuery('#logwindow').removeClass('open')
						} else {
							var size = Basic.Placer.getWindowSize();
							jQuery('#logwindow').width((size.width/2 > 400) ? size.width/2 : 400);
							jQuery('#logwindow').height((size.height/2 > 300) ? size.height/2 : 300);
							jQuery('#logwindow').css('overflow','auto');
							jQuery('#logwindow').addClass('open')
						}
					});
				}
				jQuery('#logwindow').append('<div>'+ line +'</div>');
			}
		}
    },

    punchoutOnlyLockout : function ()
    {
        if (typeof this.punchout_only_text == 'object') {
            Basic.Modal.open(this.punchout_only_text.url);
        } else {
            Basic.Modal.show('');
            Basic.Modal.updateContent(this.punchout_only_text);
        }
        jQuery('.basicModalClose').hide();
    },

    browserIsIe : function ()
    {
        if (navigator.userAgent.indexOf('MSIE') > 0) {
            return true;
        }
        return false;
    },

    cookieMessage : function ()
    {
        if (this.browserIsIe()) {
            if (typeof this.cookie_message_ie == 'object') {
                Basic.Modal.open(this.cookie_message_ie.url);
            } else {
                Basic.Modal.show('');
                Basic.Modal.updateContent(this.cookie_message_ie);
                jQuery("a#cookieLaunch").bind('click',jQuery.proxy(this.cookieAccept,this));
            }
        } else {
            if (typeof this.cookie_message == 'object') {
                Basic.Modal.open(this.cookie_message.url);
            } else {
                Basic.Modal.show('');
                Basic.Modal.updateContent(this.cookie_message);
                jQuery("a#cookieLaunch").bind('click',jQuery.proxy(this.cookieAccept,this));
            }
        }
        jQuery('.basicModalClose').remove();
    },

    cookieSetup1 : function ()
    {
        Basic.Modal.show('');
        if (this.loadSession()) {
            /*
            if (this.checkSession()) {
                Basic.Modal.updateContent('Session cookies should now be enabled.');
                if (opener) {
                    opener.location.reload();
                }
                if (self.name == 'cookieaccept') {
                    self.close();
                }
                return;
            }
            */
        }
        Basic.Modal.updateContent('This site requires cookies to maintain your session.<br>' +
            'If cookies are enabled, they may be blocked by your browser.<br>' +
            '<a href="?'+ this.query_param +'='+ jQuery.url().param(this.query_param) +'&csetup=step2">Click here</a> to ' +
            'launch the step2 accepting the session cookies.');
        jQuery('.basicModalClose').remove();
    },

    /**
     * set a cookie
     */
    setCookie : function (name, value, args)
    {
    	var info = [];
    	if (typeof args == 'undefined') {
    		info = { path: this.cookie_path }
    	} else {
    		info = args
    	}
    	jQuery.cookie(name, value, info);
    },

    /**
     * read a cookie
     */
    getCookie : function (name)
    {
    	return jQuery.cookie(name);
    },

    /**
     * delete a cookie
     */
    deleteCookie : function (name)
    {
    	return jQuery.cookie(name, null, { expires: -1 , path : this.cookie_path });
    },

    cookieSetup2 : function ()
    {
        Basic.Modal.show('');
        if (this.loadSession()) {
            if (opener) {
                opener.location.reload();
            }
            Basic.Modal.updateContent('Your session cookies should now be accepted.');
            setTimeout(function () {
                self.close()
            },5000);
        }
        jQuery('.basicModalClose').remove();
    },

    cookieAccept : function ()
    {
        this.setCookie(this.cookie_name, this.session_id);
        if (this.setCookie(this.cookie_name) != this.session_id) {
            if (this.browserIsIe()) {
                this.cookieSetIE();
            } else {
                this.cookieSetWindow();
            }
        } else {
            Basic.Modal.show('');
            Basic.Modal.updateContent('If this window does not automatically refresh, please <a href="'+ self.location.href +'">click here</a>.');
            self.location.reload();
        }
    },

    cookieSetIE : function ()
    {
        var windowSize = Basic.Placer.getWindowSize();
        var w = windowSize.width;
        var h = windowSize.height;
        var l = (screen.width - w)/2;
        var t = (screen.height - h)/2;
        var args = 'resizable=1,menubar=0,location=0,scrollbars=1,status=0,toolbar=0';
        window.external_punchout = window.open(self.location.href,'external_punchout','width='+ w +',height='+ h +',top='+ t +',left='+ l +','+ args);
        Basic.Modal.show('');
        Basic.Modal.updateContent('Please leave this window open.');
    },

    cookieSetWindow : function ()
    {
        var w = 10;
        var h = 10;
        var args = 'resizable=0,menubar=0,location=0,scrollbars=0,status=0,toolbar=0';
        window.cookieaccept = window.open(self.location.href,'cookieaccept','width='+ w +',height='+ h +',top='+ w +',left='+ h +','+ args);
        Basic.Modal.show('');
        Basic.Modal.updateContent('Please wait...');
        cookieaccept.onload = function () {
            self.focus();
            Basic.Modal.updateContent('If this window does not automatically refresh, please <a href="'+ self.location.href +'">click here</a>.');
            window.cookieaccept.close();
            self.location.reload();
        }
        setTimeout(function () {
            Basic.Modal.updateContent('If this window does not automatically refresh, please <a href="'+ self.location.href +'">click here</a>.');
            window.cookieaccept.close();
        },5000);
    }


} //End prototype