function iemOutput() {

    this.windowTimer = null;

    this.displayCartList = function( cartRows ) {

        var htm = '';
        var rowCount = 0;

        for( var lineID in cartRows ) {

            rowCount++;

            var row = cartRows[ lineID ];

            htm += '<form name="frm' + lineID + '" onsubmit="if(this.productQty.value>0){iem.CartUpdate( \'[LineID] = [' + lineID + ']\', { \'fld' + lineID + '_' + row[ 'Qty' ][ 'index' ] + '\' : this.productQty.value } );iem.CartList( \'[Completed] = [-1]\' );iem.CartSubmit( window.location );}else{alert(\'Please enter a quantity\');}return false;">' +
                '<tr>' +
                ' <td rowspan="2" valign="top">' +
                ( row[ 'Image_Thumbnail' ][ 'value' ] ? ' <img src="' + row[ 'Image_Thumbnail' ][ 'value' ] + '" border="0" alt="' + row[ 'Product_Name' ][ 'value' ] + '" />' : '&nbsp;' ) +
                ' </td>' +
                ' <td colspan="4">' +
            '    <h2 style="padding-bottom: 0; margin-bottom: 0">' + row[ 'Product_Code' ][ 'value' ] + '</h2>';

            for( var i = 1; i <= 5; i++ ) {

				if( row[ 'Option_' + i ][ 'value' ] != 0 ) {
					htm += '<br /><strong>' + row[ 'Option_' + i ][ 'value' ].replace( '|', ':</strong> ' );
				}

            }

            htm += ' </td>' +
                '</tr>' +
                '<tr>' +
                ' <td colspan="2">Quantity <input type="text" name="productQty" value="' + row[ 'Qty' ][ 'value' ] + '" size="2" maxlength="3" /> x £' + row[ 'Base_Price' ][ 'value' ] + '</td>' +
                ' <td class="price"><strong>Total £' + row[ 'Sub_Total' ][ 'value' ] + '</strong></td>' +
                ' <td class="price"><input type="submit" value="Update" />&nbsp;' +
                '<input type="button" value="Remove" onclick="iem.CartDelete( \'[LineID] = [' + lineID + ']\' );iem.CartList( \'[Completed] = [-1]\' );iem.CartSubmit();return false;" /></td>' +
                '</tr>' +
                '<tr><td colspan="5"><hr style="color: #666666" /></td></tr>' +
            '</form>';
        }
        if( ! rowCount ) {
            htm += '<tr><td colspan="5">Sorry, your shopping basket is currently empty.<br /><br /></td></tr>';
        }
        document.write( htm );
    }

    this.displayCartPreview = function( cartRows ) {

        var htm = '';

        for( var lineID in cartRows ) {

            var row = cartRows[ lineID ];

            htm += '<h2>Product Code: ' + row[ 'Product_Code' ][ 'value' ] + '</h2>' +
                '<form name="frm' + lineID + '" onsubmit="iem.CartUpdate( \'[LineID] = [' + lineID + ']\', { \'fld' + lineID + '_' + row[ 'Completed' ][ 'index' ] + '\' : \'-1\', \'fld' + lineID + '_' + row[ 'Qty' ][ 'index' ] + '\' : this.productQty.value } );iem.CartList( \'[Completed] = [-1]\' );iem.CartSubmit();return false;">' +
            '<table cellpadding="0" cellspacing="0" border="0">';

            for( var i = 1; i <= 5; i++ ) {
                if( row[ 'Option_' + i ][ 'options' ] ) {

                    htm += '<tr>';
                    htm += '<th>' + row[ 'Option_' + i ][ 'optName' ] + '</th>';
                    htm += '<td>';

                    var optCount = 0;
                    for( var idx in row[ 'Option_' + i ][ 'options' ] ) optCount++;

                    if( optCount > 1 ) {
                        htm += '<select name="Option_' + i + '" onchange="iem.CartUpdate( \'[Product_ID] = [' + row[ 'Product_ID' ][ 'value' ] + '] and [Completed] = [0]\', { \'fld' + lineID + '_' + row[ 'Option_' + i ][ 'index' ] + '\' : this[ this.selectedIndex ].value } );iem.CartList( \'[Product_ID] = [' + row[ 'Product_ID' ][ 'value' ] + '] and [Completed] = [0]\' );iem.CartSubmit( window.location );">';
                		for( var idx in row[ 'Option_' + i ][ 'options' ] ) {
                        	htm += '<option value="' + idx + '"' + ( idx == row[ 'Option_' + i ][ 'value' ] ? ' selected="selected"' : '' ) + '>' + row[ 'Option_' + i ][ 'options' ][ idx ][ 0 ] + '</option>';
                		}
                        htm += '</select>';
                    } else {
                		for( var idx in row[ 'Option_' + i ][ 'options' ] ) {
                        	htm += row[ 'Option_' + i ][ 'options' ][ idx ][ 0 ];
                		}
                    }

                    htm += '</td>';
                    htm += '</tr>';
                }
            }

            htm += '<tr>' +
                '<th>Quantity</th>' +
                '<td><input type="text" name="productQty" value="' + row[ 'Qty' ][ 'value' ] + '" size="2" maxlength="3" class="qty" title="Enter Quantity here..." /> @ £' + row[ 'Base_Price' ][ 'value' ] + '</td>' +
                '</tr>' +
                '</table>' +
                '<input type="submit" value="Add to basket" class="add" />' +
            '</form>';
        }
        document.write( htm );
    }

    this.displayCartTotal = function( totals ) {

        var htm = '';

        var lookup = {
            'Product_Total' : 'Subtotal',
            'Shipping_Total' : 'Delivery (Mainland UK Only)',
            'Grand_Total' : 'TOTAL (inc VAT)'
        }

        for( var total in totals ) {
            if( lookup[ total ] ) {
                htm += '<tr>' +
                    '<td colspan="3"><strong>' + ( lookup[ total ] ? lookup[ total ] : total ) +  '</strong></td>' +
                    '<td class="price">£' + totals[ total ] + '</td>' +
                    '<td>&nbsp;</td>' +
                '</tr>';
            }
        }

        document.write( htm );
    }

    this.displayCheckout = function( flds, currPage, frmAction ) {
        var htm = '';

        var req = new Array();

        // print out all hidden fields
        for( var fld in flds ) {
            if( flds[ fld ][ 'type' ] == 'HIDDEN' ) {
                htm += '<input type="hidden" name="' + fld + '" value="' + flds[ fld ][ 'value' ] + '" />\n';
            }
        }

        switch( currPage ) {
            case '1' : {
                htm += '<h1>Step 1: Your details</h1>';
                req = new Array( 'First_Name', 'Surname', 'EMail', 'Address_1', 'Town', 'County', 'Postcode', 'Country' );
                break;
            }
            case '2' : {
                htm += '<h1>Step 2: Delivery details</h1>';
                req = new Array( 'Delivery_Town', 'Delivery_County', 'Delivery_Postcode', 'Delivery_Country' );
                break;
            }
            case '3' : {
                htm += '<h1>Step 3: Card details</h1>';
                req = new Array( 'Card_Name', 'Card_Type', 'Card_Number', 'Card_End' );
                break;
            }
        }

        htm += '<table>\n\n';


        // print out input fields
        for( var fld in flds ) {
            if( flds[ fld ][ 'type' ] != 'HIDDEN' ) {

                var reqMark = '';

                for( var r = 0; r < req.length; r++ ) {
                    if( req[ r ] == fld ) {
                        reqMark = '*';
                    }
                }
                
                var fldName = 'fld' + flds[ fld ][ 'idx' ] + '_1';

                switch( fld ) {
                    case 'Address_2' :
                    case 'Mobile' :
                    case 'Fax' : {
                        // fields omitted from form
                        break;
                    }
                    case 'Title' : {
                        htm += '<tr><th>' + fld.split( '_' ).join( ' ' ) + ' ' + reqMark + '</th><td>';
                        htm += '<select name="' + fldName + '">' +
                            '<option>Mr</option>' +
                            '<option>Mrs</option>' +
                            '<option>Ms</option>' +
                            '<option>Miss</option>' +
                        '</select>' +
                        '</td></tr>';
                        break;
                    }
                    case 'Address_1' : {
                        htm += '<tr><th>Address ' + reqMark + '</th><td>';
                        htm += '<input type="text" name="' + fldName + '" value="' + flds[ fld ][ 'value' ] + '" class="text" />';
                        break;
                    }
                    case 'Country' :
                    case 'Delivery_Country' : {
                        htm += '<tr><th>' + fld.split( '_' ).join( ' ' ) + ' ' + reqMark + '</th><td>';
                        htm += 'United Kingdom';
                        htm += '<input type="hidden" name="' + fldName + '" value="United Kingdom" />' +
                        '</td>';
                        break;
                    }
                    case 'Card_Number' : {
                        htm += '<tr><th>' + fld.split( '_' ).join( ' ' ) + ' ' + reqMark + '</th><td>';
                        htm += '<input type="text" class="text" name="' + fldName + '" value="" onchange="this.value=this.value.replace( /[^0-9]*/g, \'\' );" />' +
                        '</td></tr>';
                        break;
                    }
                    case 'Card_Type' : {
                        
                        var cardTypes = new Array( 'Mastercard', 'Visa', 'Electron', 'Switch', 'Solo', 'HSBC' );
                        
                        htm += '<tr><th>' + fld.split( '_' ).join( ' ' ) + ' ' + reqMark + '</th><td>';
                        htm += '<select name="' + fldName + '">';
                        htm += '<option value=""></option>';
                        for( var i = 0; i < cardTypes.length; i++ ) {
                            htm += '<option value="' + cardTypes[ i ] + '">' + cardTypes[ i ] + '</option>';
                        }
                        htm += '</select>' + 
                        '</td></tr>';
                        break;
                    }
                    case 'Card_Start' :
                    case 'Card_End' : {

                        // generate month drop down
                        var months = new Array( 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' );
                        htm += '<tr><th>' + fld.split( '_' ).join( ' ' ) + ' ' + reqMark + '</th><td>';
                        htm += '<select name="' + fldName + '_mm" onchange="this.form[ \'' + fldName + '\' ].value=this.form[ \'' + fldName + '_mm\' ][ this.form[ \'' + fldName + '_mm\' ].selectedIndex ].value + \'/\' + this.form[ \'' + fldName + '_yyyy\' ][ this.form[ \'' + fldName + '_yyyy\' ].selectedIndex ].value">';
                        htm += '<option value=""></option>';
                        for( var i = 0; i < 12; i++ ) {
                            htm += '<option value="' + ( i + 1 ) + '">' + months[ i ] + '</option>';
                        }
                        htm += '</select>';

                        // generate year drop down
                        var currDate = new Date();
                        var currYear = currDate.getFullYear();
                        var maxAge = 5;

                        htm += '<select name="' + fldName + '_yyyy" onchange="this.form[ \'' + fldName + '\' ].value=this.form[ \'' + fldName + '_mm\' ][ this.form[ \'' + fldName + '_mm\' ].selectedIndex ].value + \'/\' + this.form[ \'' + fldName + '_yyyy\' ][ this.form[ \'' + fldName + '_yyyy\' ].selectedIndex ].value">';
                        htm += '<option value=""></option>';
                        if( fld == 'Card_Start' ) {
                            for( var i = currYear; i > currYear - maxAge; i-- ) {
                                htm += '<option value="' + i + '">' + i + '</option>';
                            }
                        } else {
                            for( var i = currYear; i < currYear + maxAge; i++ ) {
                                htm += '<option value="' + i + '">' + i + '</option>';
                            }
                        }
                        htm += '</select>';
                        htm += '<input type="hidden" name="' + fldName + '">' +
                        '</td></tr>';
                        break;
                    }
                    default : {
                        htm += '<tr><th>' + fld.split( '_' ).join( ' ' ) + ' ' + reqMark + '</th><td>';
                        switch( flds[ fld ][ 'type' ] ) {
                            case 'LARGE_TEXT' : {
                                htm += '<textarea name="' + fldName + '" value="' + flds[ fld ][ 'value' ] + '" class="text"></textarea>';
                                break;
                            }
                            case 'BOOL' : {
                                htm += '<input type="checkbox" style="border: 0" name="' + fldName + '" />';
                                break;
                            }
                            default: {
                                htm += '<input type="text" name="' + fldName + '" value="' + flds[ fld ][ 'value' ] + '" class="text" />';
                                break;
                            }
                        }
                        htm += '</td></tr>\n';
                        break;
                    }
                }
                
            }
        }
        if( currPage == 1 ) {
            htm += '<tr><th colspan="2"><p><input type="checkbox" style="border: 0" onclick="this.form.nextPage.value = ( this.checked ? 3 : 2 );" /> Use this address for delivery</p></th></tr>';
        }

        htm += '<tr><th colspan="2"><input type="submit" value="Continue &raquo;" /><br /><br /></th></tr>';

        // confirm address details
        if( currPage == 3 ) {
            htm += '<tr><td colspan="2"><strong>Your details</strong></td></tr>\n';
            for( var fld in flds ) {
                if( flds[ fld ][ 'type' ] == 'HIDDEN' ) {
                    if( fld != 'cartId' && fld != 'location' && fld != 'func_1' && fld != 'nextPage' ) {
                        htm += '<tr><td colspan="2">' + flds[ fld ][ 'value' ] + '</td></tr>\n';
                        //htm += '<tr><th>' + fld.split( '_' ).join( ' ' ) + '</th><td>' + flds[ fld ][ 'value' ] + '</td></tr>\n';
                    }
                }
            }
            htm += '<tr><th>&nbsp;</th><td>&nbsp;</td></tr>';
        }
        htm += '</table>\n\n';



        var reqCmd = '';
        for( var i = 0; i < req.length; i++ ) {
            if( flds[ req[ i ] ] ) {
                reqCmd += 'this.fld' + flds[ req[ i ] ][ 'idx' ] + '_1';
            } else {
                reqCmd += 'this.' + req[ i ];
            }
            if( i < req.length - 1 ) {
                reqCmd += ', ';
            }
        }

        htm = '<form name="frmCheckout" method="post" action="' + frmAction + '" onsubmit="return iem.output.validateForm(' + reqCmd + ');">' + htm + '</form>\n\n';

        document.write( htm );
    }

    this.displayCartConfirm = function( success, cartError, cartErrNo ) {
        var htm = '';
        if( success ) {
            htm += '<h1>Thank you</h1>'
            htm += '<p>Your order details have been sent successfully and will receive our immediate attention.</p>';
            htm += '<p><a href="javascript:window.close();">Close Window</a></p>';
        } else {
            
            htm += '<h1>Error</h1>';

            if( cartError ) {
                if( cartErrNo >= 500 ) {
                    htm += '<p>Error validating email address, please use a different email address or try again later</p>';
                }
                htm += '<p>' + cartErrNo + ' - ' + cartError + '</p>';
            }
            htm += '<p><a href="javascript:window.history.go(-1);">Back</a></p>';
        }
        document.write( htm );
    }

    this.displayCheckoutWin = function( checkoutUrl ) {
        window.location = checkoutUrl;
    }

    this.windowMonitor = function( win ) {
        if( win.closed ) {
            iem.win.location.reload();
            clearInterval( iem.output.windowTimer );
        }
    }


    this.validateForm = function() {

        var flds = iem.output.validateForm.arguments;
        var val = true;
        var err = '';

        for( var i = 0; i < flds.length; i++ ) {
            if( flds[ i ] ) {
                if( typeof( flds[ i ].type ) != 'undefined' ) {
                    switch( flds[ i ].type ) {
                        case 'select-one' : {
                            if( ! flds[ i ].options[ flds[ i ].selectedIndex ].value ) {
                                val = false;
                                err += flds[ i ].name + ' must be selected.\n';
                            }
                            break;
                        }
                        case 'checkbox' : {
                            if( ! flds[ i ].checked ) {
                                val = false;
                                err += flds[ i ].name + ' must be checked.\n';
                            }
                            break;
                        }
                        default : {
                            if( ! flds[ i ].value ) {
                                val = false;
                                err += flds[ i ].name + ' must be completed.\n';
                            }
                        }
                    }
                } else {
                    var chk = false;
                    for( var btn = 0; btn < flds[ i ].length; btn++ ) {
                        if( flds[ i ][ btn ].type == 'radio' ) {
                            if( flds[ i ][ btn ].checked ) chk = true;
                        }
                    }
                    if( ! chk ) {
                        val = false;
                        err += flds[ i ].name + ' must be selected.\n';
                    }
                }
            }
        }
        if( ! val ) {
            //if( err ) {
                //alert( err );
            //} else {
                alert( 'Please complete all required fields.' );
            //}
        }
        return val;
    }
}
