/*
    IEM shopping cart
*/

function iemClient( varName, cart, interfacePath, resourcePath, listPath, warningPath, win, siteHostName ) {

    this.name = varName;
    this.cart = cart;
    this.output = null;
    this.interfacePath = interfacePath;
    this.resourcePath = resourcePath;
    this.listPath = listPath;
    this.warningPath = warningPath;
    this.win = ( win ? win : top );
    this.siteHostName = siteHostName;
    this.active = false;
    this.request = null;
    this.response = null;
    this.cartCmds = new Array();
    this.cartCmds[ 0 ] = new Array();
    this.checkoutWin = null;
    this.checkoutTimer = null;
    this.funcNo = 1;
    this.locale = 0;

    //this.debug = true;

    this.CartAdd = function( productId, productQty, inputFlds, productCompleted, filter ) {
        // add a new product to cart

        if( ! filter ) {
            // backwards compatibility: if filter is omitted, build one using productId
            var filter = '[Product_ID] = [' + productId + ']';
        }
        this.cartCmds[ this.funcNo ] = {
            'func' : 'CartAdd',
            'productQty' : productQty,
            'productCompleted' : productCompleted ? -1 : 0,
            'filter' : filter
        }
        // add any input fields which might have been set
        if( inputFlds ) {
            for( var opt in inputFlds ) {
                this.cartCmds[ this.funcNo ][ opt ] = inputFlds[ opt ];
            }
        }
        this.funcNo++;
        return true;
    }

    this.CartClear = function( quiet ) {
        // delete all lines from the cart
        // quiet specifies whether the user should be prompted before deletion

        if( quiet ) {
            var confirmDelete = true;
        } else {
            // prompt user to confirm deletion
        	var confirmDelete = this.PromptConfirm( 'Are you sure you want to remove all products from your basket?');
        }

    	if( confirmDelete ) {
            this.cartCmds[ this.funcNo ] = { 'func' : 'CartClear' }
            this.funcNo++;
            return true;
    	}
    	return false;
    }

    this.PerpetuateVal = function( idx, val ) {
        // perpetuate a value that belongs to no particular cart function
        this.cartCmds[ 0 ][ idx ] = val;
    }

    this.CartRegisterFields = function( isNew ) {
        this.cartCmds[ this.funcNo ] = {
            'func' : 'CartRegisterFields'
        }
        if( isNew ) {
            this.cartCmds[ this.funcNo ][ 'new' ] = isNew;
        }
        this.funcNo++;
    }

    this.CallFunc = function( funcName, flds ) {
        // generic method to call any cart function by name
        // the second argument can optionally be an associative array of IEM parameters
        this.cartCmds[ this.funcNo ] = { 'func' : funcName }
        if( flds ) {
            for( var fld in flds ) {
                this.cartCmds[ this.funcNo ][ fld ] = flds[ fld ];
            }
        }
        this.funcNo++;
        return true;
    }

    this.CartCreate = function() {
        return this.CallFunc( 'CartCreate' );
    }

    this.CartDelete = function( filter, quiet ) {
        // delete rows from the cart
        // quiet specifies whether the user should be prompted before deletion

        if( filter ) {
            // user prompted for confirmation of deletion

            if( quiet ) {
                var confirmDelete = true;
            } else {
                var confirmDelete = this.PromptConfirm( 'Are you sure you want to remove this product from your basket?' );
            }

            if( confirmDelete ) {
                this.cartCmds[ this.funcNo ] = {
                    'func'   : 'CartDelete',
                    'filter' : filter
                }
                this.funcNo++;
                return true;
        	} else {
        		return false;
        	}
        } else {
            // no filter set, so delete all rows
            return this.CartClear( quiet );
        }
    }

    this.GetWindowLocation = function() {
        if( this.siteHostName ) {
            return this.win.location.protocol + '//' + this.siteHostName + this.win.location.pathname + this.win.location.search + this.win.location.hash;
        } else {
            return this.win.location;
        }
    }

    this.CartInit = function() {
        // initialise shopping cart

        if( typeof( this.cart ) == 'object' ) {
          	if( this.cart.cookiesEnabled ) {
             	// store the request and response in global vars

                this.request  = this.cart.getRequest();
                this.response = this.cart.getResponse();

           	 	if( this.response.getField( 'active' ) == 'false' ) {
                    // cookies are enabled, but the cart hasnt yet been created
                    this.CallFunc( 'CartCreate' );
                    this.CartSubmit( this.GetWindowLocation() );
        		}
        		this.active = true;
        		return true;
        	} else {
        	    // cookies are disabled
        	    // could warn the user here that the cart is unusable without cookies
        	    return false;
            }
        } else {
            // cart unavailable
            // could redirect to error reporting at this point
            this.cart = null;
            return false;
        }
    }

    this.CartList = function( filter ) {
        this.cartCmds[ this.funcNo++ ] = {
            'func'   : 'CartList',
            'filter' : ( filter ? filter : '' )
        }
        return true;
    }

    this.CartPreview = function( prodId, callback, prodOptions ) {

        if( this.active ) {
            var cartErrNo = parseInt( this.response.getField( 'cartErrNo' ) );
            var filter = '';
            
            if( typeof( prodId ) == 'object' ) {
                for( var theId in prodId ) {
                    filter += '[Product_ID] = [' + prodId[ theId ] + '] and [Completed] = [0] or ';
                }                
                filter = filter.substring( 0, filter.length - 3 );
            } else {
                filter = '[Product_ID] = [' + prodId + '] and [Completed] = [0]';
            }
            if( ! cartErrNo ) {
                if( this.GetLastFunc() == 'CartList' && ( this.request.getField( 'filter_1' ) == filter || this.request.getField( 'filter_2' ) == filter ) ) {

                    var prods = this.response.getField( 'CartList' );

                    if( prods[ 'Rows' ] && prods[ 'Rows' ][ 0 ] ) {
                        this.GenCartList( callback );
                    } else {
                        if( typeof( prodId ) == 'object' ) {                            
                            for( var theId in prodId ) {
                                this.CartAdd( prodId[ theId ], 1, null );
                            }
                        } else if( typeof( prodOptions ) == 'object' ) {                            
                            for( var theOption in prodOptions ) {
                                for( var optionIdx in prodOptions[ theOption ] ) {
                                    var inputFlds = new Object;
                                    inputFlds[ theOption ] = prodOptions[ theOption ][ optionIdx ];
                                    this.CartAdd( prodId, 1, inputFlds );    
                                }                                
                            }
                        } else {
                            this.CartAdd( prodId, 1, null );
                        }
                        this.CartList( filter );
                        this.CartSubmit( this.GetWindowLocation() );
                    }
                } else {
                    this.CartList( filter );
                    this.CartSubmit( this.GetWindowLocation() );
                }
            }
        }
    }


    this.CartSubmit = function( redirect, replacePage ) {
        // submit whatever is held in the cartCmds array

        var cartUrl = '';

        if( this.cart ) {
            if( this.cart.cookiesEnabled ) {
                cartUrl = 'http://' + this.interfacePath + '?' + this.GetUrl() + 'location=' + ( redirect ? redirect : this.listPath );
            } else {
                // cookies are disabled, redirect to warning page
                if( this.warningPath ) {
                    cartUrl = this.warningPath;
                } else {
                    this.PromptError( '', 'Cookies must be enabled before proceeding.' );
                }
            }
            if( cartUrl ) {
                if( ! replacePage ) {
                    this.win.location = cartUrl;
                } else {
                    this.win.location.replace( cartUrl );
                }
                // empty the cartCmds array
                this.cartCmds = new Array();
            }
        } else {
            // shopping cart unavailable
            // redirect to error reporting page
            return false;
        }
    }

    this.CartUpdate = function( filter, inputFlds ) {
        //  update a single line in the cart

        this.cartCmds[ this.funcNo ] = {
            'func'   : 'CartUpdate',
            'filter' : ( filter ? filter : '' )
        }
        if( inputFlds ) {
            for( var opt in inputFlds ) {
                this.cartCmds[ this.funcNo ][ opt ] = inputFlds[ opt ];
            }
        }
        this.funcNo++;
        return true;
    }


    this.OrderQuantity = function( filter ) {
        // call query on order history quantities
        this.cartCmds[ this.funcNo ] = {
            'func'   : 'OrderQuantity',
            'filter' : ( filter ? filter : '' )
        }
        this.funcNo++;
        return true;
    }

    this.GenCartList = function( callback ) {

        if( this.active ) {

            var cartErrNo = parseInt( this.response.getField( 'cartErrNo' ) );
            var cartError = this.response.getField( 'cartError' );

            //if( this.GetLastFunc() == 'CartList' && ! cartErrNo ) {
            if( ! cartErrNo ) {

                var cartRows = new Array();

                var prods = this.response.getField( 'CartList' );
                var rows = prods[ "Rows" ];
                var fields = prods[ "Fields" ];
                var options = prods[ "Options" ];
                var masterOptions = prods[ "MasterOptions" ];
                var masterNames = prods[ "MasterNames" ];
                
           		var fldIdx = Object();
        		if( fields ) {
        			for( col in fields[ 0 ] ) {
        				fldIdx[ fields[ 0 ][ col ] ] = col;
        			}
        		}

        		for( var row in rows ) {

        			var lineID = rows[ row ][ fldIdx[ 'LineID' ] ];

                    cartRows[ lineID ] = new Array();

        			for( var col in rows[ row ] ) {

                        var fldType = fields[ 1 ][ col ];
                        var fldName = fields[ 0 ][ col ];

                        cartRows[ lineID ][ fldName ] = {
                            'value' : rows[ row ][ col ],
                            'type'  : fields[ 1 ][ col ],
                            'index' : col
                        }

                        switch( fldType ) {
                            case 'RESOURCE' : {
                                cartRows[ lineID ][ fldName ][ 'value' ] = ( rows[ row ][ col ] ? this.resourcePath + rows[ row ][ col ] : '' );
                                break;
                            }
                            case 'RULE' : {
                				var optIdx = 0;
                				if( options && options[ row ] ) {
            						if( optIdx = options[ row ][ col ] ) {
            						    cartRows[ lineID ][ fields[ 0 ][ col ] ][ 'optName' ] = masterNames[ optIdx ];
            							cartRows[ lineID ][ fields[ 0 ][ col ] ][ 'options' ] = masterOptions[ optIdx ];
            						}
                				}
                                break;
                            }
                            case 'MONEY' : {
                                cartRows[ lineID ][ fldName ][ 'value' ] = this.formatCurrency( cartRows[ lineID ][ fldName ][ 'value' ] );
                            }
                            default: {


                            }
                        }
        			}
        		}
        		if( typeof( callback ) == 'function' ) {
                    callback( cartRows );
                }
            } else {
                this.PromptError( cartErrNo, cartError );
                this.CartList();
                this.CartSubmit( this.GetWindowLocation() );
            }
        }
    }

    this.GenCartTotal = function( callback ) {

        if( this.active ) {
            var cartErrNo = parseInt( this.response.getField( 'cartErrNo' ) );

            //if( this.GetLastFunc() == 'CartList' && ! cartErrNo ) {
            if( ! cartErrNo ) { 
                var totals = new Array();

                var prods = this.response.getField( 'CartList' );

                for( var total in prods[ 'Totals' ][ 0 ] ) {                    
                    if( typeof( prods[ 'Totals' ][ 1 ][ total ] ) == 'object' ) {
                        
                        for( var row in prods[ 'Totals' ][ 1 ][ total ] ) {
                            prods[ 'Totals' ][ 1 ][ total ][ row ] = this.formatCurrency( prods[ 'Totals' ][ 1 ][ total ][ row ] );    
                        }                        
                        
                        totals[ prods[ 'Totals' ][ 0 ][ total ] ] = prods[ 'Totals' ][ 1 ][ total ];
                    } else {
                        totals[ prods[ 'Totals' ][ 0 ][ total ] ] = this.formatCurrency( prods[ 'Totals' ][ 1 ][ total ] );    
                    }
                }
                if( typeof( callback ) == 'function' ) {
                    callback( totals );
                }
            }
        }
    }

    this.GenRegisterForm = function( callback, frmProtocol, frmLocation, funcNo ) {

        if( ! funcNo ) funcNo = 1;   

        var prods = this.response.getField( 'CartRegisterFields' );

        var flds = new Array();
        var fldNames = prods[ 'Fields' ][ 0 ];
        var fldTypes = prods[ 'Fields' ][ 1 ];
        var fldVals = prods[ 'Rows' ][ 0 ];
        var requestFlds = this.request.getFields();

        var options = prods[ 'Options' ][ 0 ];
        var masterNames = prods[ 'MasterNames' ];
        var masterOptions = prods[ 'MasterOptions' ];

        for( var idx in fldNames ) {

            var opts = false;
            var optName = '';
            var optIdx = 0;

            if( optIdx = options[ idx ] ) {
				optName = masterNames[ optIdx ];
				opts = masterOptions[ optIdx ];
			}

            flds[ fldNames[ idx ] ] = { 'type' : fldTypes[ idx ], 'options' : opts, 'value' : ( requestFlds[ idx ] ? requestFlds[ idx ] : ( fldVals[ idx ] ? fldVals[ idx ] : '' )  ), 'idx' : idx }
            
            if( fldNames[ idx ] == 'Country' || fldNames[ idx ] == 'Delivery_Country' ) {
                flds[ fldNames[ idx ] ][ 'value' ] = ( fldVals[ idx ] ? fldVals[ idx ] : 'UNITED KINGDOM' );
            }
        }
        
        if( funcNo != 1 ) {
            flds[ 'func_1' ]   = { 'type' : 'HIDDEN', 'value' : 'CartList' }
            flds[ 'filter_1' ] = { 'type' : 'HIDDEN', 'value' : '[Completed] = [-1]' }
        }
        flds[ 'func_' + funcNo ] = { 'type' : 'HIDDEN', 'value' : ( iem.response.getField( 'usr' ) != '' ? 'CartRegisterUpdate' : 'CartRegister' ) }
        flds[ 'location' ] = { 'type' : 'HIDDEN', 'value' : ( frmLocation ? frmLocation : this.GetWindowLocation() ) }

        var frmPage   = 1;
        var frmType   = 'register';
        var frmAction = ( frmProtocol ? frmProtocol : 'http' ) + '://' + this.interfacePath;

        if( typeof( callback ) == 'function' ) {
            callback( flds, frmPage, frmAction, frmType );
        }
    }

    this.GenCheckoutForm = function( callback, frmProtocol, frmLocation, singlePage, funcNo ) {
    // generate fields for the checkout form

        //var singlePage = false;

        if( ! funcNo ) funcNo = 1;   

        var prods = this.response.getField( 'CartCheckoutFields' );

        var currPage = ( this.request.getField( 'nextPage' ) ? parseInt( this.request.getField( 'nextPage' ) ) : 1 );

        var flds = new Array();
        var fldNames = prods[ 'Fields' ][ 0 ];
        var fldTypes = prods[ 'Fields' ][ 1 ];
        var fldVals  = prods[ 'Rows' ][ 0 ];

        var options = prods[ 'Options' ][ 0 ];
        var masterNames = prods[ 'MasterNames' ];
        var masterOptions = prods[ 'MasterOptions' ];

        
        if( funcNo != 1 ) {
            flds[ 'func_1' ]   = { 'type' : 'HIDDEN', 'value' : 'CartList' }
            flds[ 'filter_1' ] = { 'type' : 'HIDDEN', 'value' : '[Completed] = [-1]' }
        }
        flds[ 'func_' + funcNo ]   = { 'type' : 'HIDDEN', 'value' : ( currPage < 3 && ! singlePage ? 'CartCheckoutFields' : 'CartCheckout' ) }
        flds[ 'nextPage' ] = { 'type' : 'HIDDEN', 'value' : parseInt( currPage ) + 1 }
        flds[ 'location' ] = { 'type' : 'HIDDEN', 'value' : ( frmLocation ? frmLocation : this.GetWindowLocation() ) }

        for( var idx in fldNames ) {

            // check whether this field is needed on this step of the checkout
            
            if( singlePage ) {
                var useField = true;
            } else {
                var useField = false;
                var fieldRules = {
                    //'1' : ( ( fldNames[ idx ].indexOf( 'Card_' ) == -1 && fldNames[ idx ].indexOf( 'Delivery_' ) == -1 ) || fldNames[ idx ].indexOf( 'Delivery_Country' ) == 0 ),
                    '1' : ( ( fldNames[ idx ].indexOf( 'Card_' ) == -1 && fldNames[ idx ].indexOf( 'Delivery_' ) == -1 ) ),
                    '2' : ( fldNames[ idx ].indexOf( 'Delivery_' ) == 0 && fldNames[ idx ].indexOf( 'Delivery_Method' ) != 0 ),
                    '3' : ( fldNames[ idx ].indexOf( 'Card_' ) == 0 || fldNames[ idx ].indexOf( 'Delivery_Method' ) == 0 )
                }
    
                useField = ( singlePage ? true : fieldRules[ currPage ] );
            }

            if( useField ) {
                var opts = false;
                var optName = '';
                var optIdx = 0;

                if( optIdx = options[ idx ] ) {
    				optName = masterNames[ optIdx ];
    				opts = masterOptions[ optIdx ];
    			}
  			
                flds[ fldNames[ idx ] ] = {
                    'idx'     : idx,
                    'type'    : fldTypes[ idx ],
                    'options' : opts,
                    'value'   : ( fldVals[ idx ] ? fldVals[ idx ] : '' )
                }
                if( currPage == '1' ) {
                    if( fldNames[ idx ] == 'Delivery_Country' ) {
                        flds[ fldNames[ idx ] ][ 'type' ] == 'HIDDEN';
                    }
   			    }
                if( fldNames[ idx ] == 'Country' || fldNames[ idx ] == 'Delivery_Country' ) {
                    flds[ fldNames[ idx ] ][ 'value' ] = ( fldVals[ idx ] ? fldVals[ idx ] : 'UNITED KINGDOM' );
                }
            } else {
                if( fldVals[ idx ] ) {
                    flds[ 'fld' + idx + '_' + funcNo ] = {
                        'type'    : 'HIDDEN',
                        'value'   : fldVals[ idx ]
                    }
                }
            }
        }

        // allow custom overwriting of fields by passing them on the current URL
        var params = this.parseGetVars();
        for( var param in params ) {
            flds[ param ] = {
                'type'    : 'HIDDEN',
                'value'   : params[ param ]
            };
        }

        var frmType   = 'checkout';
        var frmAction = frmProtocol + '://' + this.interfacePath;

        if( typeof( callback ) == 'function' ) {
            callback( flds, currPage, frmAction, frmType );
        }
    }

    this.GenCheckoutConfirm = function( callback ) {

        var cartErrNo = parseInt( this.response.getField( 'cartErrNo' ) );
        var cartError = this.response.getField( 'cartError' );

        if( ! cartErrNo  ) {
            var params = this.parseGetVars();
            cartErrNo = params[ 'cartErrNo' ];
            cartError = params[ 'cartError' ];
        }

        if( cartErrNo ) {
            callback( false, cartError, parseInt( cartErrNo ) );
        } else {
            callback( true );
        }
    }

    this.GetLastFunc = function() {
        // returns the name of the last cart function requested

        var lastFunc = '';

        if( this.request ) {
            var flds = this.request.getFields();

            for( var fld in flds ) {
                if( fld.substring( 0, 5 ) == 'func_' ) {
                    lastFunc = flds[ fld ];
                }
            }
        }
        return lastFunc;
    }

    this.GetUrl = function() {
        // build query string to call the cart functions
        var cartUrl = 'cartId=' + this.response.getField( 'cartId' ) + '&';

        // cartCmds[ 0 ] is reserved for perpetuated values
        for( var cmd in this.cartCmds[ 0 ] ) {
            cartUrl += cmd + '=' + escape( this.cartCmds[ 0 ][ cmd ] ) + '&';
        }
        // other items in the cartCmds array are parameters to func_1, func_2, etc
        for( var funcNo = 1; funcNo < this.cartCmds.length; funcNo++ ) {
            for( var cmd in this.cartCmds[ funcNo ] ) {
                cartUrl += cmd + '_' + funcNo + '=' + escape( this.cartCmds[ funcNo ][ cmd ] ) + '&';
            }
        }
        return cartUrl;
    }

    this.ProceedCheckout = function( redirect, callback ) {

        this.cartCmds[ this.funcNo ] = { 'func' : 'CartCheckoutFields' }

        var cartUrl = 'http://' + this.interfacePath + '?' + this.GetUrl() + 'location=' + ( redirect ? redirect : '' );

        if( typeof( callback ) == 'function' ) {
            callback( cartUrl );
        }
    }

    this.PromptConfirm = function( msg ) {
        return confirm( msg );
    }

    this.PromptError = function( cartErrNo, cartError ) {
        switch( parseInt( cartErrNo ) ) {
            case '301' : {
                alert( 'Sorry, the product code you have entered does not exist.\nPlease check and try again.' );
            }
            default: {
                alert( cartError );
            }
        }
    }

    this.ProductList = function( filter ) {
        this.cartCmds[ this.funcNo ] = {
            'func' : 'ProductList',
            'filter' : filter
        }
        this.funcNo++;
        return true;
    }

    this.getSign = function() {
        var signs = new Array( '£', '$' );
        return signs[ this.locale ];
    }

    this.formatCurrency = function( num ) {
        num = num.toString().replace( /\$|\,/g, '' );
        if( isNaN( num ) ) {
            num = '0';
        }
        sign = ( num == ( num = Math.abs( num ) ) );
        num = Math.floor( num * 100 + 0.50000000001 );
        cents = num % 100;
        num = Math.floor( num / 100 ).toString();
        if( cents < 10 ) {
            cents = '0' + cents;
        }
        for( var i = 0; i < Math.floor( ( num.length - ( 1 + i ) ) / 3 ); i++ ) {
            num = num.substring( 0, num.length - ( 4 * i + 3 ) ) + ',' + num.substring( num.length - ( 4 * i + 3 ) );
        }
        //return ( ( ( sign ) ? '' : '-' ) + this.getSign() + num + '.' + cents );
        return ( ( ( sign ) ? '' : '-' ) + num + '.' + cents );
    }

    this.parseGetVars = function() {
        // splits the query string from the url
        // returns associative array of HTTP get vars

        var args = new Array();
        var query = window.location.search.substring( 1 );
        if( query ) {
            var strList = query.split( '&' );
            for( str in strList ) {
                var parts = strList[ str ].split( '=' );
                args[ unescape( parts[ 0 ] ) ] = unescape( parts[ 1 ] );
            }
        }
        return args;
    }

    this.CartInit();
}

