
-- BidManiac is an addon whose purpose is to simplify the bidding on items
-- in raids or groups by automating the drudgery of keeping track of
-- everyone's bids.

-----------------------------------------------------------------
-- DO NOT MODIFY ANYTHING BELOW THIS LINE -----------------------
-----------------------------------------------------------------

-- TODO:
-- - Lots of stuff, but I can't remember any right now (or now).

-- CONOP
-- A central hash table containing charname,bidamount is maintained, and is
-- called BidManiac_bidMatrix.
-- A minimum bid is required, and any bids below that amount will be rejected.
-- A bid state is maintained to keep track of where in the auction process we are.
-- The bidState variable can have several values: 0 (cleared or beginning state of
-- auction), goingOnce (going once state reached), goingTwice (going twice state
-- reached).
--
-- GUI/functionality: The GUI is separated from the functionality of the addon
-- by an intermediary set of functions.  All GUI (and WoW) event handlers have
-- the form BidManiac_On*().  Most of these just call a true handler function,
-- and are included for flexibility should the GUI design change.
-- The internal functionality methods again begin with BidManiac_, but the first
-- word of the rest of the function name is lowercase (BidManiac_startBidding()).
-- All GUI updates are handled by a separate function called
-- BidManiac_updateGUI().  This function basically just updates visibility
-- of the buttons and other GUI components based on states of the program
-- and GUI (shown/hidden).

-- The character name.
local BidManiac_charName = "" ;

-- isBidding is true when an auction is in progress, even if it is paused.
local BidManiac_isBidding = false ;

-- isPaused is true if an auction is paused.
-- Persistent condition: (isPaused == true) iff (isBidding == true)
local BidManiac_isPaused = false ;

-- The item being bid on.  This is in the normal WoW form for an item link,
-- including control chars etc.
local BidManiac_itemLink = "" ;

-- bidMatrix is a hashtable of charname,bidamount pairs.
-- This matrix is cleared with the Clear button in the GUI.
local BidManiac_bidMatrix = {} ;

-- The minimum allowed bid.  Bidding this amount will be accepted (as long as no
-- higher bids are active).
-- This is a saved variable, configurable with the GUI.
BidManiac_minAllowedBid = 6 ;

-- This is the minimum allowed bid increment for each new bid.
-- Setting this to 0 will allow tie bidding.
-- This is a saved variable, configurable with the GUI.
BidManiac_minBidIncrement = 1 ;

-- The audience to which the auction notifications are sent.
-- This is a saved variable, configurable with the GUI.
BidManiac_audience = "RAID_WARNING" ;

-- These three variables control the lengths of the intervals for the going
-- once, twice, sold notifications.
-- Each time represents the time to go from one state to another (relative times,
-- not absolute).
-- These are saved variables, configurable with the GUI.
BidManiac_goingOnceTime = 8 ;
BidManiac_goingTwiceTime = 8 ;
BidManiac_goneTime = 8 ;

-- lastUpdateTime is the last time that a state changed occured.  This includes
-- bidState 0 to goingOnce, goingOnce to goingTwice, goingOnce to 0,
-- and goingTwice to 0.  This variable is reset if an auction is paused.
local BidManiac_lastUpdateTime = 0 ;

-- Possible bidStates:
-- 0: No auction going on, or goingOnce not reached
-- goingOnce: going once notice has been reached
-- goingTwice: going twice notice has been reached
local BidManiac_goingOnce = 1 ;
local BidManiac_goingTwice = 2 ;
local BidManiac_bidState = 0 ;

-- remoteLoad allows the loading of an itemLink to be performed
-- by whisper from another user.
-- This is a saved variable, configurable via the GUI.
BidManiac_remoteLoad = false ;

-- BidManiac_privateAuction is true if the name of the high bidder is hidden, false
-- if the name is to be hidden.
BidManiac_privateAuction = true ;

--
-- BidManiac_Print()
-- Print a message to the console.
--
function BidManiac_Print( msg )
if( msg ==  nil ) then
	DEFAULT_CHAT_FRAME:AddMessage( "Print> msg is nil", 1, 1, 1 ) ;
else
	DEFAULT_CHAT_FRAME:AddMessage( msg, 1, 1, 1 ) ;
end
end -- BidManiac_Print()

--
-- BidManiac_PrintAll()
-- Print a message to the bidding audience.
--
function BidManiac_PrintAll( msg )
if( msg == nil ) then
	BidManiac_Print( "PrintAll> msg is nil" ) ;
else
--	BidManiac_Print( "PrintAll> msg: " .. msg .. ", BidManiac_audience: " .. BidManiac_audience ) ;
	SendChatMessage( msg, BidManiac_audience ) ;
end
end -- BidManiac_PrintAll()

--
-- BidManiac_Reply()
-- Send a message to the given player.
--
function BidManiac_Reply( player, msg )
if( player == nil ) then
	BidManiac_Print( "Reply> player is nil" ) ;
elseif( msg == nil ) then
	BidManiac_Print( "Reply> msg is nil" ) ;
else
--	BidManiac_Print( "Reply> msg: " .. msg .. ", WHISPER, nil, player: " .. player ) ;
--  Use nil as the language, will default to orcish for the horde, and common for the alliance
--  Thanks slyxx
	SendChatMessage( msg, "WHISPER", nil, player ) ;
end
end -- BidManiac_Reply()

--
-- BidManiac_OnLoad()
-- This function is called when the interface is loaded.
-- Outputs usage message, and registers for slash commands.
--
function BidManiac_OnLoad()
-- BidManiac_Print( "BidManiac_OnLoad()" ) ;

BidManiac_Print( "Loaded BidManiac 2.00, use /bm to initialize bidding interface" );

-- Register the slash command handlers
-- /bm brings up the interface.
SlashCmdList[ "BIDMANIAC" ] = BidManiac_SlashCommand ;
SLASH_BIDMANIAC1 = "/bm" ;

-- /bmstatus is a debugging tool to output current internal state.
-- Not necessary for normal operation.
SlashCmdList[ "BIDMANIACSTATUS" ] = BidManiac_SlashStatusCommand ;
SLASH_BIDMANIACSTATUS1 = "/bmstatus" ;

-- /bmload is used to load an itemlink for auctioning.
SlashCmdList[ "BIDMANIACLOAD" ] = BidManiac_SlashLoadCommand ;
SLASH_BIDMANIACLOAD1 = "/bmload" ;

-- Register to be notified when variables have been loaded.
this:RegisterEvent( "CHAT_MSG_WHISPER" ) ;
this:RegisterEvent( "VARIABLES_LOADED" ) ;

-- Make frame closable with escape key.
-- TODO: Not working for some reason, Blizzard may have changed something.
tinsert( UISpecialFrames, "BidManiac" ) ; 

-- Convenience value.
BidManiac_charName = UnitName( "player" ) ;

-- Set internal variables to a known state.
BidManiac_clearAll() ;

end -- BidManiac_OnLoad()

--
-- BidManiac_SlashLoadCommand()
-- Handle loading an itemlink for auctioning.
--
function BidManiac_SlashLoadCommand( arg )
-- BidManiac_Print( "BidManiac_SlashLoadCommand()" ) ;

if( (arg == nil) or (arg == "") ) then
	BidManiac_Print( "Usage: /bmload <item link>" ) ;
	return ;
end

BidManiac_itemLink = arg ;
-- BidManiac_Print( "BidManiac_SlashLoadCommand> Set itemLink to: "
--	.. BidManiac_stripItemLink( arg ) ) ;

-- Update the GUI to reflect the new item, this will basically set the
-- GUI text field giving positive confirmation that an item link is loaded.
BidManiac_updateGUI() ;

end -- BidManiac_SlashLoadCommand

--
-- BidManiac_RemoteLoadCheckButtonToggle()
-- Invoked when the user clicks the remote load check button.
--
function BidManiac_RemoteLoadCheckButtonToggle()
if( BidManiac_RemoteLoadCheckButton:GetChecked() == nil ) then
	BidManiac_remoteLoad = false ;
else
	BidManiac_remoteLoad = true ;
end

-- No need to update the GUI here since the check box functionality
-- is part of the component itself.
--BidManiac_Print( "BidManiac_RemoteLoadCheckButtonToggle> BidManiac_remoteLoad: " ..
--	BidManiac_getBoolString( BidManiac_remoteLoad ) ) ;
end -- BidManiac_RemoteLoadCheckButtonToggle

--
-- BidManiac_PrivateAuctionCheckButtonToggle()
--
function BidManiac_PrivateAuctionCheckButtonToggle()
if( BidManiac_PrivateAuctionCheckButton:GetChecked() == nil ) then
	BidManiac_privateAuction = false ;
else
	BidManiac_privateAuction = true ;
end

-- No need to update the GUI here since the check box functionality
-- is part of the component itself.
--BidManiac_Print( "BidManiac_PrivateAuctionCheckButtonToggle> BidManiac_privateAuction: " ..
--	BidManiac_getBoolString( BidManiac_privateAuction ) ) ;
end -- BidManiac_PrivateAuctionCheckButtonToggle

--
-- BidManiac_AudienceDropDownOnLoad()
-- Invoked when the audience drop down list box is loaded.
--
function BidManiac_AudienceDropDownOnLoad()
-- BidManiac_Print( "BidManiac_AudienceDropDownOnLoad" ) ;
UIDropDownMenu_Initialize(this, BidManiac_AudienceDropDownInitialize);
end -- BidManiac_AudienceDropDownOnLoad

--
-- BidManiac_AudienceDropDownInitialize()
-- Populate the audience drop down list box.
-- This will be called basically everytime the GUI is raised,
-- or whenever the user clicks on the drop down arrow.
--
function BidManiac_AudienceDropDownInitialize()
-- BidManiac_Print( "BidManiac_AudienceDropDownInitialize" ) ;

info = {};
info.func = BidManiac_AudienceDropDownOnClick;

info.text = "RAID_WARNING" ;
info.value = "RAID_WARNING" ;
UIDropDownMenu_AddButton(info);

info.text = "PARTY" ;
info.value = "PARTY" ;
UIDropDownMenu_AddButton(info);

info.text = "RAID" ;
info.value = "RAID" ;
UIDropDownMenu_AddButton(info);
	
info.text = "GUILD" ;
info.value = "GUILD" ;
UIDropDownMenu_AddButton(info);
	
info.text = "SAY" ;
info.value = "SAY" ;
UIDropDownMenu_AddButton(info);
	
info.text = "YELL" ;
info.value = "YELL" ;
UIDropDownMenu_AddButton(info);

-- Set the last known value of this drop down box.
UIDropDownMenu_SetSelectedValue( BidManiac_AudienceDropDown, BidManiac_audience ) ;

end -- BidManiac_AudienceDropDownInitialize

--
-- BidManiac_AudienceDropDownOnClick()
-- Invoked whenever the user selects an item in the drop down box.
--
function BidManiac_AudienceDropDownOnClick()
-- BidManiac_Print( "BidManiac_AudienceDropDownOnClick> this.value: " .. this.value ) ;

-- Update the displayed value.
UIDropDownMenu_SetSelectedValue(BidManiac_AudienceDropDown, this.value);

-- Update internal state.
BidManiac_audience = this.value ;
end -- BidManiac_AudienceDropDownOnClick

--
-- BidManiac_OnShow()
-- Invoked whenever the GUI is shown.
--
function BidManiac_OnShow()
-- By definition, for the BM to be hidden, no auction is active.
-- Therefore, only need to ensure the interface elements are updated.
-- BidManiac_clearAll() ;
BidManiac_updateGUI() ;
end

--
-- BidManiac_OnHide()
-- Invoked whenever the GUI is hidden.
--
function BidManiac_OnHide()
-- Shutdown bidding, enforce precondition for OnShow().
-- The argument to stopBidding() will ensure that the audience is notified.
-- This will essentially stop any auction when the BM window is minimized.
-- TODO: Perhaps this functionality should be rethought?  Opening the game
--  map will close the window, and thus stop the auction.
BidManiac_stopBidding( true ) ;
BidManiac_clearAll() ;
BidManiac_updateGUI() ;
end

--
-- BidManiac_OnUpdate()
-- Invoked several times per second (10?) if the GUI is open.
-- elapsed is the time since OnUpdate() was last invoked.
--
function BidManiac_OnUpdate( elapsed )
if( (BidManiac_isBidding == false) and (BidManiac_isPaused == false) ) then
    -- No auction active (or paused).
    return ;
end

-- Call the local update handler.
BidManiac_handleUpdate() ;

end -- BidManiac_OnUpdate()

--
-- BidManiac_OnEvent()
-- Generic event handler.
--
function BidManiac_OnEvent( event )
-- BidManiac_Print( "BidManiac_OnEvent()" ) ;

if( event == "VARIABLES_LOADED" ) then
--	BidManiac_Print( "BidManiac_OnEvent> Setting BidManiac_AudienceDropDown to: "
--		.. BidManiac_audience ) ;

	-- Variables loaded, set internal state and GUI data.
	-- TODO: Could I just call clearAll() and updateGUI() here?
	UIDropDownMenu_SetSelectedValue( BidManiac_AudienceDropDown, BidManiac_audience ) ;
	BidManiac_minAllowedBidSlider:SetValue( BidManiac_minAllowedBid ) ;

	BidManiac_minBidIncrementSlider:SetValue( BidManiac_minBidIncrement ) ;
	local minBidText = "Min Increment: " .. BidManiac_minBidIncrement ;
	if( BidManiac_allowTieBids() ) then
		minBidText = minBidText .. " (Ties OK)" ;
	end
	BidManiac_minBidIncrementSliderText:SetText( minBidText ) ;

	BidManiac_goingOnceTimeSlider:SetValue( BidManiac_goingOnceTime ) ;
	BidManiac_goingOnceTimeSliderText:SetText( "Going Once: " ..
		BidManiac_goingOnceTime .. " seconds" ) ;
	BidManiac_goingTwiceTimeSlider:SetValue( BidManiac_goingTwiceTime ) ;
	BidManiac_goingTwiceTimeSliderText:SetText( "Going Twice: " ..
		BidManiac_goingTwiceTime .. " seconds" ) ;
	BidManiac_goneTimeSlider:SetValue( BidManiac_goneTime ) ;
	BidManiac_goneTimeSliderText:SetText( "Gone: " ..
		BidManiac_goneTime .. " seconds" ) ;
	BidManiac_RemoteLoadCheckButton:SetChecked( BidManiac_remoteLoad ) ;
	BidManiac_PrivateAuctionCheckButton:SetChecked( BidManiac_privateAuction ) ;

end -- VARIABLES_LOADED

-- BidManiac_Print( "BidManiac_OnEvent> event: " .. event ) ;
if( event == "CHAT_MSG_WHISPER" ) then
	-- Someone sent us a whisper, it could be a bid, or remote load.
    BidManiac_OnWhisper( arg1, arg2 ) ;
end -- CHAT_MSG_WHISPER

end -- BidManiac_OnEvent()

--
-- BidManiac_OnWhisper()
-- Check for a bid or remote load command.
--
function BidManiac_OnWhisper( textSent, playerSource )
-- BidManiac_Print( "BidManiac_OnWhisper( " .. textSent .. ", " .. playerSource .. " )" ) ;

if( BidManiac_remoteLoad == true ) then
	-- Remote load is currently being accepted, check for the proper format.
-- 	BidManiac_Print( "BidManiac_OnWhisper> remoteLoad is true" ) ;
--	BidManiac_Print( "BidManiac_OnWhisper> strsub: "
--		.. strsub( string.lower( textSent ), 1 ) ) ;
	if( strsub( string.lower( textSent ), 1, 6 ) == "bmload" ) then
		-- Someone sent a remote load command, and remote loads are currently
		-- being accepted.

		-- Get the new item link.
		-- BUG: No verification is permitted on the proper format of the given itemLink.
		-- BUG: But do I really care if someone bids for some_chars_mom?
		BidManiac_itemLink = strsub( textSent, 8 ) ;

		-- Display the link.
		BidManiac_updateGUI() ;
--		BidManiac_Print( "BidManiac_OnWhisper> Updated itemLink: " .. BidManiac_itemLink ) ;

		-- Have a nice day.
		return ;
	end -- if( strsub() )
end -- if( BidManiac_remoteLoad == true )

if( BidManiac_isBidding == true ) then
	-- Check for an info request
	if( (textSent ~= nil) and (strsub( string.lower( textSent ), 1, 4 ) == "info") ) then
		BidManiac_handleInfoCommand( playerSource ) ;
	end
end -- BidManiac_isBidding == true

if( (BidManiac_isBidding == false) or (BidManiac_isPaused == true) ) then
    -- Not bidding, no need to look at this.
	-- BidManiac_Print( "BidManiac_OnWhisper> No auction active" ) ;
    return ;
end
-- State: an auction is active, and active (not paused).
-- BidManiac_Print( "BidManiac_OnWhisper> Auction active" ) ;

-- BidManiac_isBidding is true, and BidManiac_isPaused is false.
-- Attempt to see if the message is a bid.
-- Example: /w auctioneer_charname 8
-- (bids 8)
-- Need to parse the textSent.
if( (textSent == nil) or (textSent == "") ) then
	-- No argument.
--	BidManiac_Print( "BidManiac_OnWhisper> Empty textSent" ) ;
    return ;
end

-- Check for an integer (no fractional bids permitted).
if( BidManiac_isInteger( textSent ) ) then
    -- It's an integer, woohoo!
--    BidManiac_Print( "BidManiac_OnWhisper> Found a number" ) ;

	-- Call the bid handler.
    BidManiac_handleBid( tonumber( textSent ), playerSource ) ;
else
    -- Unknown bid, assume it's just a normal chat message to the user.
--    BidManiac_Print( "BidManiac_OnWhisper> Normal chat?" ) ;
end

end -- BidManiac_OnWhisper

--
-- BidManiac_handleInfoCommand( playerSource )
-- Handle a request for current bid information.
-- There is no important code here, just string manipulation.
-- Precondition: Auction active, but perhaps paused
--
function BidManiac_handleInfoCommand( playerSource )
-- BidManiac_Print( "BidManiac_handleInfoCommand> playerSource: " .. playerSource ) ;

-- Build the infoText string which will be sent to the player
-- requesting the auction information.
local infoText = "Current auction for " .. BidManiac_itemLink
	.. " is " ;

-- Output auction state.
if( BidManiac_isPaused == true ) then
	infoText = infoText .. "PAUSED.  " ;
else
	infoText = infoText .. "ACTIVE.  " ;
end

-- Report high bid (if any).
infoText = infoText .. "Current high bid is " ;
if( BidManiac_noBids() ) then
	-- Special case:
	-- If there are no bids active, then no need to enumerate the max bid (below),
	-- just reply to the user and return from here.
	infoText = infoText .. "(none)." ;
	BidManiac_Reply( playerSource, infoText ) ;
	return ;
end -- BidManiac_noBids()

-- There is at least one bid, report it/them.
infoText = infoText .. BidManiac_getMaxBid() .. ".  " ;

-- Include information about the number of bidders, and if
-- this user is the high bidder (or tied for high bid).
if( BidManiac_bidMatrix[ playerSource ] ~= nil ) then
	-- This user is at least tied for the high bid, if not the sole owner.

	-- Is this player the sole high bidder?
	if( BidManiac_getNumBids() > 1 ) then
		-- No, tie bidding.
		infoText = infoText .. "You are currently tied with "
			.. (BidManiac_getNumBids() - 1)
			.. " other bidder" ;
		if( BidManiac_getNumBids() > 2 ) then
			infoText = infoText .. "s" ;
		end
		infoText = infoText .. "." ;
	else
		-- playerSource is the only bidder.
		infoText = infoText .. "You are currently the high bidder." ;
	end
else
	-- User is not in the BidMatrix, thus not a high bidder.
	if( BidManiac_getNumBids() > 1 ) then
		infoText = infoText .. "There are currently "
			.. BidManiac_getNumBids()
			.. " bidders tied, and you are NOT one of them." ;
	else
		-- Only one bidder, and playerSource is not that person.
		infoText = infoText .. "You are currently NOT the high bidder." ;
	end
end -- BidMatrix[ playerSource ] ~= nil

BidManiac_Reply( playerSource, infoText ) ;

end -- BidManiac_handleInfoCommand()

--
-- BidManiac_isInteger()
-- Return nil if this is NOT an integer, otherwise return tonumber().
--
function BidManiac_isInteger( arg )
-- No numbers with decimal points are permitted.
-- The 'true' argument here disables regex, and uses lexical matching instead.
if( string.find( arg, ".", 1, true ) ~= nil ) then
--	BidManiac_Print( "BidManiac_isInteger> Found a decimal: " .. arg ) ;
	return nil ;
end

-- No decimal point, let tonumber() do the rest of the work.
return tonumber( arg ) ;
end -- BidManiac_isInteger()

--
-- BidManiac_SlashCommand()
-- Load the interface.
--
function BidManiac_SlashCommand( msg )
-- Show() will invoke OnShow(), which will call updateGUI().
BidManiacFrame:Show() ;
end -- BidManiac_SlashCommand()

--
-- BidManiac_SlashStatusCommand()
-- Handles /bmstatus, prints some debugging information to the console.
--
function BidManiac_SlashStatusCommand( msg )
BidManiac_Print( "BidManiac_isBidding: " .. BidManiac_getBoolString( BidManiac_isBidding ) ) ;
BidManiac_Print( "BidManiac_isPaused: " .. BidManiac_getBoolString( BidManiac_isPaused ) ) ;
BidManiac_Print( "BidManiac_itemLink: " .. BidManiac_itemLink ) ;
BidManiac_Print( "BidManiac_minAllowedBid: " .. BidManiac_minAllowedBid ) ;
BidManiac_Print( "BidManiac_audience: " .. BidManiac_audience ) ;
BidManiac_Print( "BidManiac_bidState: " .. BidManiac_bidState ) ;
BidManiac_Print( "BidManiac_minBidIncrement: " .. BidManiac_minBidIncrement ) ;
BidManiac_Print( "BidManiac_goingOnceTime: " .. BidManiac_goingOnceTime ) ;
BidManiac_Print( "BidManiac_goingTwiceTime: " .. BidManiac_goingTwiceTime ) ;
BidManiac_Print( "BidManiac_goneTime: " .. BidManiac_goneTime ) ;
BidManiac_Print( "BidManiac_lastUpdateTime: " .. BidManiac_lastUpdateTime ) ;
BidManiac_Print( "BidManiac_remoteLoad: " .. BidManiac_getBoolString( BidManiac_remoteLoad ) ) ;
BidManiac_Print( "BidManiac_privateAuction: " .. BidManiac_getBoolString( BidManiac_privateAuction ) ) ;
BidManiac_Print( "time: " .. time() ) ;

-- Output all active bidders and bids.
for k,v in pairs(BidManiac_bidMatrix) do
	BidManiac_Print( "BidManiac_bidMatrix[ " .. k .. " ]: " .. v ) ;
end -- for

end -- BidManiac_SlashStatusCommand()

--
-- BidManiac_OnEscape()
-- Invoked when the escape key is pressed.
-- TODO: This doesn't get called in some situations, something to do with
-- the logFrameEditBox focus.
--
function BidManiac_OnEscape()
BidManiac_Print( "BidManiac_OnEscape()" ) ;
-- The same functionality is provided by the close button.
BidManiac_OnCloseButtonClick() ;
end

--
-- BidManiac_OnStartButtonClick()
-- Invoked when the start button is clicked.
-- Precondition: Start button is only enabled (and thus this handler can
-- only be called) when a valid item link exists.
--
function BidManiac_OnStartButtonClick()
-- BidManiac_Print( "BidManiac_OnStartButtonClick()" ) ;

BidManiac_startBidding() ;
BidManiac_updateGUI() ;
end

--
-- BidManiac_OnStopButtonClick()
-- Invoked when the stop button is clicked.
--
function BidManiac_OnStopButtonClick()
-- BidManiac_Print( "BidManiac_OnStopButtonClick()" ) ;

-- Stop the auction, and notify the audience.
BidManiac_stopBidding( true ) ;
BidManiac_updateGUI() ;
end

--
-- BidManiac_OnPauseButtonClick()
-- Invoked when the user presses the pause button.
-- Pause the current auction.
--
function BidManiac_OnPauseButtonClick()
-- BidManiac_Print( "BidManiac_OnPauseButtonClick()" ) ;

BidManiac_pauseBidding() ;
BidManiac_updateGUI() ;
end

--
-- BidManiac_OnResumeButtonClick()
-- Invoked when the user presses the resume button.
-- Resume the current auction.
--
function BidManiac_OnResumeButtonClick()
-- BidManiac_Print( "BidManiac_OnResumeButtonClick()" ) ;

BidManiac_resumeBidding() ;
BidManiac_updateGUI() ;
end

--
-- BidManiac_OnClearButtonClick()
-- Invoked when the user presses the clear button.
-- Clear auction state, most notably the bidMatrix and itemLink.
--
function BidManiac_OnClearButtonClick()
-- BidManiac_Print( "BidManiac_OnClearButtonClick()" ) ;

BidManiac_clearAll() ;
BidManiac_updateGUI() ;
end

--
-- BidManiac_OnClearLogButtonClick()
-- Invoked when the user presses the clearlog button.
-- Clear the auction log.
--
function BidManiac_OnClearLogButtonClick()
-- BidManiac_Print( "BidManiac_OnClearLogButtonClick" ) ;
BidManiac_LogFrameEditBox:SetText( "" ) ;

end -- BidManiac_OnClearLogButtonClick

--
-- BidManiac_OnSelectAllButtonClick()
-- Invoked when the user presses the select all button.
-- Selects all text in the frame editbox.
--
function BidManiac_OnSelectAllButtonClick()
-- BidManiac_Print( "BidManiac_OnSelectAllButtonClick" ) ;

-- Set the focus to the editbox.  This makes it easy to copy with ctrl-c.
BidManiac_LogFrameEditBox:SetFocus() ;

-- Select all text in the LogFrameEditBox.
BidManiac_LogFrameEditBox:HighlightText() ;

end -- BidManiac_OnSelectAllButtonClick

--
-- BidManiac_OnCloseButtonClick()
-- Invoked when the user presses the close button.
--
function BidManiac_OnCloseButtonClick()
-- BidManiac_Print( "BidManiac_OnCloseButtonClick()" ) ;

-- Stop the bidding, if active.
-- If it is active or paused then output a message saying it was stopped.
BidManiac_stopBidding( BidManiac_isBidding or BidManiac_isPaused ) ;

-- Hide the frame.
BidManiacFrame:Hide() ;
end

--
-- BidManiac_updateGUI()
-- Update the GUI components.  This is invoked when a variable changes
-- that is presented to the user via the GUI.
--
function BidManiac_updateGUI()
-- BidManiac_Print( "BidManiac_updateGUI()" ) ;

-- Set the running/paused/stopped indication text.
if( BidManiac_isBidding ) then
	if( BidManiac_isPaused ) then
		BidManiac_StatusFontString:SetText( "Paused" ) ;
	else
		BidManiac_StatusFontString:SetText( "Running" ) ;
	end
else
	-- Not bidding
	BidManiac_StatusFontString:SetText( "Stopped" ) ;
end

BidManiac_updateButtons() ;

-- Update the itemLink GUI component.
BidManiac_ItemFontString:SetText( "Item: " .. BidManiac_itemLink ) ;

-- Update the current bid GUI component (includes bid and bidders).
BidManiac_BidFontString:SetText( BidManiac_getCurrentBidFontStringText() ) ;
end -- BidManiac_updateGUI()

--
-- BidManiac_getCurrentBidFontStringText()
-- Returns the current bid and all bidders in string format.
-- Convenience function.
--
function BidManiac_getCurrentBidFontStringText()
-- BidManiac_Print( "BidManiac_getCurrentBidFontStringText()" ) ;

BidManiac_outputString = "Bid: " ;
if( not BidManiac_noBids() ) then
	-- An active bid exists.
	BidManiac_outputString = BidManiac_outputString .. BidManiac_getMaxBid()
		.. " (" .. BidManiac_getHighBidNames() .. ")" ;
end
return BidManiac_outputString ;
end -- BidManiac_getCurrentBidFontStringText

--
-- BidManiac_noBids()
-- Return true if no bids exist.
-- Return false otherwise.
--
function BidManiac_noBids()
if( BidManiac_getMaxBid() == (BidManiac_minAllowedBid - 1) ) then
	return true ;
else
	return false ;
end
end -- BidManiac_noBids()

--
-- BidManiac_updateButtons()
-- GUI update function that enables/disables the GUI buttons as appropriate
-- to auction state.
--
function BidManiac_updateButtons()
-- BidManiac_Print( "BidManiac_updateButtons()" ) ;
if( not BidManiacFrame:IsVisible() ) then
	-- GUI is hidden.
    -- Nothing to do as far as buttons are concerned, wasted CPU to mess
    -- with this.
--    BidManiac_Print( "BidManiac_updateButtons> Not visible." ) ;
    return ;
end

if( BidManiac_isBidding == true ) then
	-- Auction active.
	BidManiac_ClearButton:Disable() ;
    BidManiac_StartButton:Disable() ;
    BidManiac_StopButton:Enable() ;
    
    -- No changing the minimum allowed bid is permitted.
	-- TODO
    
    if( BidManiac_isPaused == true ) then
		-- Paused auction.
        -- Only Resume and stop should be visible
        BidManiac_PauseButton:Disable() ;
        BidManiac_ResumeButton:Enable() ;
    else
        -- Paused is false, auction active in normal running state
        BidManiac_PauseButton:Enable() ;
        BidManiac_ResumeButton:Disable() ;
    end
else
    -- BidManiac_isBidding is false, no auction going on
	BidManiac_ClearButton:Enable() ;
    if( BidManiac_itemLink ~= "" ) then
        -- itemLink is valid, we can start if ordered
        BidManiac_StartButton:Enable() ;
    else
		BidManiac_StartButton:Disable() ;
    end
	    
    BidManiac_StopButton:Disable() ;
    BidManiac_PauseButton:Disable() ;
    BidManiac_ResumeButton:Disable() ;
end -- if( BidManiac_isBidding )

end -- BidManiac_updateButtons()

--
-- BidManiac_startBidding()
-- Start the auction.
-- Precondition: itemLink is valid.
--
function BidManiac_startBidding()
-- BidManiac_Print( "BidManiac_startBidding()" ) ;

local minBidString = "Minimum bid increment is " .. BidManiac_minBidIncrement ;
if( BidManiac_allowTieBids() ) then
	minBidString = minBidString .. " (Ties ENABLED)" ;
else
	minBidString = minBidString .. " (Ties DISABLED)" ;
end

local pubPrivString = "Private" ;
if( BidManiac_privateAuction == false ) then
	pubPrivString = "Public" ;
end -- if( private )

-- Notify the audience that an auction is beginning.
BidManiac_PrintAll( " Auction started for " .. BidManiac_itemLink ..
       ".  " .. minBidString
       .. ".  Whisper "
       .. BidManiac_charName .. " to bid. {skull}ONLY WISPER NUMBER{skull}" ) ;
     
BidManiac_Log( "Start: " .. BidManiac_itemLink ) ;

BidManiac_isBidding = true ;
BidManiac_isPaused = false ;

-- Set the lastUpdateTime and bidState, used for state changes to going once/twice/gone.
BidManiac_lastUpdateTime = time() ;
BidManiac_bidState = 0 ;

end -- BidManiac_startBidding()

--
-- BidManiac_stopBidding()
-- Worker function that stops an auction.
-- If doOutput is true, then the audience will be notified, and the event will be logged.
-- Precondition: BidManiac_isBidding is true.
--
function BidManiac_stopBidding( doOutput )
-- BidManiac_Print( "Stopping bidding on " .. BidManiac_itemLink ) ;
if( doOutput == true ) then
	BidManiac_PrintAll( "Bidding has ended for " .. BidManiac_itemLink .. "." ) ;
	BidManiac_Log( "End: " .. BidManiac_itemLink ) ;
end

BidManiac_isBidding = false ;
BidManiac_isPaused = false ;
BidManiac_updateGUI() ;

end -- BidManiac_stopBidding()

--
-- BidManiac_pauseBidding()
-- Worker function that pauses an auction.
-- Precondition: An auction is active and not paused.
--
function BidManiac_pauseBidding()
-- BidManiac_Print( "BidManiac_pauseBidding() " ) ;

BidManiac_isPaused = true ;
BidManiac_PrintAll( "Bidding now paused for " .. BidManiac_itemLink .. "." ) ;
BidManiac_Log( "Pause: " .. BidManiac_itemLink ) ;
end -- BidManiac_pauseBidding()

--
-- BidManiac_resumeBidding()
-- Worker function that resumes a paused auction.
-- Precondition: an auction is running, but paused.
--
function BidManiac_resumeBidding()
-- BidManiac_Print( "BidManiac_resumeBidding()" ) ;

BidManiac_isPaused = false ;

-- Form the string to be sent to the audience.
BidManiac_outputString = "Bidding now resumed for " .. BidManiac_itemLink ;
if( BidManiac_noBids() ) then
	-- No bids
	BidManiac_outputString = BidManiac_outputString .. ", currently no bids." ;
else
	BidManiac_outputString = BidManiac_outputString .. ", current high bid: "
		.. BidManiac_getMaxBid() .. "." ;
end

-- BidManiac_Print( "BidManiac_resumeBidding> Resuming bidding on "
--	.. BidManiac_itemLink ) ;
BidManiac_PrintAll( BidManiac_outputString ) ;

-- Form the log string.
BidManiac_outputString = "Resume: " .. BidManiac_itemLink .. ", bid: " ;
if( BidManiac_noBids() ) then
	BidManiac_outputString = BidManiac_outputString .. "(none)" ;
else
	BidManiac_outputString = BidManiac_outputString .. BidManiac_getMaxBid() ;
end
BidManiac_Log( BidManiac_outputString ) ;

-- Be sure to reset the bid state, not fair to resume after 5 minutes of pause
-- to reach the sold! notice
BidManiac_bidState = 0 ;
BidManiac_lastUpdateTime = time() ;

end -- BidManiac_resumeBidding()

--
-- BidManiac_clearAll()
-- Initialize all internal variables.
-- Worker function, no GUI updates performed.
--
function BidManiac_clearAll()
-- BidManiac_Print( "BidManiac_clearAll> Clearing internal state" ) ;

BidManiac_itemLink = "" ;
BidManiac_isBidding = false ;
BidManiac_isPaused = false ;
BidManiac_bidMatrix = {} ;
BidManiac_lastUpdateTime = 0 ;
BidManiac_bidState = 0 ;

-- This next function call could be omitted, but it is harmless:
-- If called from OnLoad(), the checkbox will be set appropriately (necessary).
-- If clear invoked with the Clear button, then this will set the checkbox
-- to its current state (NO-OP).
BidManiac_RemoteLoadCheckButton:SetChecked( BidManiac_remoteLoad ) ;
BidManiac_PrivateAuctionCheckButton:SetChecked( BidManiac_privateAuction ) ;

end -- BidManiac_clearAll()

--
-- BidManiac_minAllowedBidSliderOnLoad()
-- Initializes the going once slider.
--
function BidManiac_minAllowedBidSliderOnLoad()
-- BidManiac_Print( "BidManiac_minAllowedBidSliderOnLoad()" ) ;

BidManiac_minAllowedBidSlider:SetMinMaxValues( 1, 50 ) ;
BidManiac_minAllowedBidSlider:SetValueStep( 1 ) ;
end -- minAllowedBid

--
-- BidManiac_minAllowedBidSliderOnValueChanged()
-- Invoked when the user modifies the minimum allowed bid slider.
--
function BidManiac_minAllowedBidSliderOnValueChanged()
BidManiac_minAllowedBid = this:GetValue() ;
--BidManiac_Print( "BidManiac_minAllowedBidSliderOnValueChanged> BidManiac_minAllowedBid: "
--	.. BidManiac_minAllowedBid ) ;
BidManiac_minAllowedBidSliderText:SetText( "Minimum Allowed Bid: " ..
	BidManiac_minAllowedBid ) ;
end -- BidManiac_minAllowedBidSliderOnValueChanged

--
-- BidManiac_minBidIncrementSliderOnLoad()
-- Initialize the minBidIncrement slider control.
--
function BidManiac_minBidIncrementSliderOnLoad()
-- BidManiac_Print( "BidManiac_minBidIncrementSliderOnLoad()" ) ;

BidManiac_minBidIncrementSlider:SetMinMaxValues( 0, 30 ) ;
BidManiac_minBidIncrementSlider:SetValueStep( 1 ) ;
end -- BidManiac_minBidIncrementSliderOnLoad()

--
-- BidManiac_goingOnceTimeSliderOnLoad()
-- Initializes the going once slider.
--
function BidManiac_goingOnceTimeSliderOnLoad()
-- BidManiac_Print( "BidManiac_goingOnceTimeSliderOnLoad()" ) ;

BidManiac_goingOnceTimeSlider:SetMinMaxValues( 1, 30 ) ;
BidManiac_goingOnceTimeSlider:SetValueStep( 1 ) ;
end -- BidManiac_goingOnceTimeSliderOnLoad

--
-- BidManiac_minBidIncrementSliderOnValueChanged()
-- Invoked when the minBidIncrementSlider value is changed.
--
function BidManiac_minBidIncrementSliderOnValueChanged()
BidManiac_minBidIncrement = BidManiac_minBidIncrementSlider:GetValue() ;
-- BidManiac_Print( "BidManiac_minBidIncrementSliderOnValueChanged> BidManiac_minBidIncrement: "
--	.. BidManiac_minBidIncrement ) ;

local minBidText = "Min Increment: " .. BidManiac_minBidIncrement ;
if( BidManiac_allowTieBids() ) then
	minBidText = minBidText .. " (Ties OK)" ;
end

BidManiac_minBidIncrementSliderText:SetText( minBidText ) ;
end -- BidManiac_minBidIncrementSliderOnValueChanged()

--
-- BidManiac_goingOnceTimeSliderOnValueChanged()
-- Invoked when the user modifies the going once slider.
--
function BidManiac_goingOnceTimeSliderOnValueChanged()
BidManiac_goingOnceTime = this:GetValue() ;
--BidManiac_Print( "BidManiac_goingOnceTimeSliderOnValueChanged> BidManiac_goingOnceTime: "
--	.. BidManiac_goingOnceTime ) ;

BidManiac_goingOnceTimeSliderText:SetText( "Going Once: " ..
	BidManiac_goingOnceTime .. " seconds" ) ;
end -- BidManiac_goingOnceTimeSliderOnValueChanged

--
-- BidManiac_goingTwiceTimeSliderOnLoad()
-- Initializes the going twice slider.
--
function BidManiac_goingTwiceTimeSliderOnLoad()
-- BidManiac_Print( "BidManiac_goingTwiceTimeSliderOnLoad()" ) ;

BidManiac_goingTwiceTimeSlider:SetMinMaxValues( 1, 30 ) ;
BidManiac_goingTwiceTimeSlider:SetValueStep( 1 ) ;
end -- BidManiac_goingTwiceTimeSliderOnLoad

--
-- BidManiac_goingTwiceTimeSliderOnValueChanged()
-- Invoked when the user modifies the going twice slider.
--
function BidManiac_goingTwiceTimeSliderOnValueChanged()
BidManiac_goingTwiceTime = this:GetValue() ;
-- BidManiac_Print( "BidManiac_goingTwiceTimeSliderOnValueChanged> BidManiac_goingTwiceTime: "
--	.. BidManiac_goingTwiceTime ) ;

BidManiac_goingTwiceTimeSliderText:SetText( "Going Twice: " ..
	BidManiac_goingTwiceTime .. " seconds" ) ;
end -- BidManiac_goingTwiceTimeSliderOnValueChanged

--
-- BidManiac_goneTimeSliderOnLoad()
-- Initializes the gone slider.
--
function BidManiac_goneTimeSliderOnLoad()
BidManiac_goneTimeSlider:SetMinMaxValues( 1, 30 ) ;
BidManiac_goneTimeSlider:SetValueStep( 1 ) ;
-- BidManiac_Print( "BidManiac_goneTimeSliderOnLoad> BidManiac_goneTime: "
--	.. BidManiac_goneTime ) ;
end -- BidManiac_goneTimeSliderOnLoad

--
-- BidManiac_goneTimeSliderOnValueChanged()
-- Invoked when the user modifies the gone slider.
--
function BidManiac_goneTimeSliderOnValueChanged()
BidManiac_goneTime = this:GetValue() ;
-- BidManiac_Print( "BidManiac_goneTimeSliderOnValueChanged> BidManiac_goneTime: "
--	.. BidManiac_goneTime ) ;
BidManiac_goneTimeSliderText:SetText( "Gone: " ..
	BidManiac_goneTime .. " seconds" ) ;
end -- BidManiac_goneTimeSliderOnValueChanged

--
-- BidManiac_handleBid()
-- Worker function invoked when a bid is received from a player.
-- This is a simple function, which attempts to eliminate one obvious
-- condition at a time.
-- Precondition: bidAmount is a valid integer, though it may not be in a
-- valid range.
--
function BidManiac_handleBid( bidAmount, playerSource )
-- BidManiac_Print( "BidManiac_handleBid> bidAmount: "
--	.. bidAmount .. ", playerSource: "
--	.. playerSource ) ;

local currentMax = BidManiac_getMaxBid() ;

-- Check if the user is bidding less than the minAllowedBid.
if( bidAmount < BidManiac_minAllowedBid ) then
	BidManiac_Reply( playerSource, "The minimum allowed bid is " ..
		BidManiac_minAllowedBid ) ;
	return ;
end

-- Is the bidAmount less than the currently bid amount?
if( bidAmount < currentMax ) then
    BidManiac_Reply( playerSource, "Your bid is too low.  The current bid is: " ..
           currentMax ) ;
    return ;
end

-- Check if the user is attempting to bid a tie amount
if( (bidAmount == currentMax) and (not BidManiac_allowTieBids()) ) then
	-- Someone is bidding the same as the current max bid, and allow ties is disabled
	BidManiac_Reply( playerSource, "Your bid is too low.  The current bid is: " ..
		currentMax .. ", and tie bids are disabled." ) ;
	return ;
end

-- Check if this is the opening bid.
if( not (currentMax == (BidManiac_minAllowedBid - 1)) ) then
	-- Not an opening bid, check for bid increment.
	-- Make sure the bid amount is at least the current max plus the minimum bid
	-- increment amount.
	if( bidAmount < (currentMax + BidManiac_minBidIncrement) ) then
		BidManiac_Reply( playerSource, "Your bid is too low.  The current bid is "
			.. currentMax .. ", and the current minimum bid increment is "
			.. BidManiac_minBidIncrement .. "." ) ;
		return ;
	end
end

-- The next two if() statements have a bit of redundancy with code located
-- elsewhere.  However, since this is the core function for handling bids,
-- I am ok with being explicit here, simply to have all core code in one place.

-- Check to see if the user already has an active bid.
-- Allow the user to bid higher than his own current bid.
-- However, the user cannot bid <= his own current bid.
if( (BidManiac_bidMatrix[ playerSource ] ~= nil) and
    (BidManiac_bidMatrix[ playerSource ] >= bidAmount) ) then
    BidManiac_Reply( playerSource, "You already have an active bid of " .. currentMax .. "." ) ;
    return ;
end

-- Looks ok, valid bid.
if( bidAmount > currentMax ) then
    -- New high bid, clear the matrix.
    BidManiac_bidMatrix = {} ;
end

-- Log this user's bid.
BidManiac_bidMatrix[ playerSource ] = bidAmount ;
BidManiac_Reply( playerSource, "Your bid of " .. bidAmount .. " has been recorded." ) ;

-- Output the new max bid to the audience, and log.
BidManiac_PrintMaxBid() ;
BidManiac_Log( playerSource .. " bid " .. bidAmount ) ;

-- Clear goingOnce and goingTwice states with new bid.
BidManiac_bidState = 0 ;

-- Ensure that the entire goingOnceTime is reused.
BidManiac_lastUpdateTime = time() ;

-- At least one element informs the user of the current bid status, so be sure
-- to update the GUI.
BidManiac_updateGUI() ;

end -- BidManiac_handleBid()

--
-- BidManiac_handleUpdate()
-- Worker function called by event handler BidManiac_OnUpdate().
-- Invoked once every time cycle (0.1 seconds), iff the GUI is being shown.
-- This function is responsible for updating bidding state.
--
function BidManiac_handleUpdate()
-- BidManiac_Print( "BidManiac_handleUpdate()" ) ;

-- Check if the auction is paused.
if( BidManiac_isPaused == true ) then
    return ;
end

-- Update bidState if necessary.
local BidManiac_currentTime = time() ;
if( BidManiac_bidState == 0 ) then
    if( (BidManiac_currentTime - BidManiac_lastUpdateTime) >= BidManiac_goingOnceTime ) then
        -- Change state to going once
        BidManiac_bidState = BidManiac_goingOnce ;
        BidManiac_updateGUI() ;
        BidManiac_PrintAll( "Current Bid {star} " .. BidManiac_getMaxBidString() .. " {star} going ONCE ("
			.. BidManiac_itemLink .. ")" ) ;
        BidManiac_lastUpdateTime = time() ;
    end
elseif( BidManiac_bidState == BidManiac_goingOnce ) then
    if( (BidManiac_currentTime - BidManiac_lastUpdateTime) >= BidManiac_goingTwiceTime ) then
        -- Change state to going twice
        BidManiac_bidState = BidManiac_goingTwice ;
        BidManiac_updateGUI() ;
        BidManiac_PrintAll( "Current Bid {star} " .. BidManiac_getMaxBidString() .. " {star} going TWICE ("
			.. BidManiac_itemLink .. ")" ) ;
        BidManiac_lastUpdateTime = time() ;
    end
elseif( BidManiac_bidState == BidManiac_goingTwice ) then
    if( (BidManiac_currentTime - BidManiac_lastUpdateTime) >= BidManiac_goneTime ) then
        -- Auction ended
        BidManiac_auctionSold() ;

		-- Stop bidding, but don't notify the audience with the normal bidding halted
		-- information because auctionSold() will output appropriately for a completed
		-- auction.
        BidManiac_stopBidding( false ) ;
        BidManiac_updateGUI() ;
    end
end

end -- BidManiac_handleUpdate

--
-- BidManiac_getMaxBid()
-- Return the current maxBid(), or minAllowedBid - 1 if no bids active.
--
function BidManiac_getMaxBid()
-- BidManiac_Print( "BidManiac_getMaxBid()" ) ;

-- By definition, all entries in the bidMatrix are the current highest bid,
-- no need to check through all of them.
for k,v in pairs(BidManiac_bidMatrix) do
    if( v >= BidManiac_minAllowedBid ) then
        -- Valid bid.
		-- BidManiac_Print( "BidManiac_getMaxBid> Returning bid: " .. v ) ;
        return v ;
    end
end -- for

-- No bids found, return the min allowed bid, minus 1, to indicate this.
-- BidManiac_Print( "BidManiac_getMaxBid> No bids found, returning: "
--	.. (BidManiac_minAllowedBid - 1) ) ;
return (BidManiac_minAllowedBid - 1) ;
end -- BidManiac_getMaxBid()

--
-- BidManiac_PrintMaxBid()
-- Output the current max bid to the bidding community.
-- Will output quantity of bids afterward, if greater than 1.
--
function BidManiac_PrintMaxBid()
-- BidManiac_Print( "BidManiac_PrintMaxBid()" ) ;
BidManiac_PrintAll( "Current Bid {star} " .. BidManiac_getMaxBidString() .. " {star}" ) ;
end

--
-- BidManiac_getMaxBidString()
-- Return the current bid string, to include max bid and bidders.
--
function BidManiac_getMaxBidString()
-- BidManiac_Print( "BidManiac_getMaxBidString()" ) ;

-- All bids in the BidMatrix must be the same, so just count the number of
-- elements, and get the bid amount.
local maxBid = BidManiac_getMaxBid() ;
if( BidManiac_noBids() ) then
    -- No bids
	return "(none)" ;
end

BidManiac_outputString = "" .. maxBid ;

if( BidManiac_getNumBids() > 1 ) then
	-- More than 1 bid, include the number of bids.
    BidManiac_outputString = BidManiac_outputString .. " (" .. BidManiac_getNumBids() .. ") " ;
end

if( BidManiac_privateAuction == false ) then
	BidManiac_outputString = BidManiac_outputString .. " (" .. BidManiac_getHighBidNames() .. ")" ;
end

-- BidManiac_Print( "BidManiac_getMaxBidString> Returning: "
--	.. BidManiac_outputString ) ;
return BidManiac_outputString ;
end -- BidManiac_PrintMaxBid()

--
-- BidManiac_getNumBids()
-- Return the number of active bids (they will all be the same bidAmount).
--
function BidManiac_getNumBids()
-- BidManiac_Print( "BidManiac_getNumBids()" ) ;

local numBids = 0 ;
for user,bid in pairs(BidManiac_bidMatrix) do
	numBids = numBids + 1 ;
end -- for

return numBids ;
end -- BidManiac_getNumBids()

--
-- BidManiac_auctionSold()
-- This function just outputs end of auction information, no internal or GUI state
-- is changed.
--
function BidManiac_auctionSold()
-- BidManiac_Print( "BidManiac_auctionSold()" ) ;

if( BidManiac_noBids() ) then
    -- No bids received
    BidManiac_PrintAll( "Item " .. BidManiac_itemLink .. " FAILED TO SELL!." ) ;
    BidManiac_Log( "Item " .. BidManiac_itemLink .. " failed to sell." ) ;
    return ;
end
-- Condition: Item sold/tied with 1 or more valid bids.

local outputString = "Item " .. BidManiac_itemLink .. " SOLD for " .. BidManiac_getMaxBid()
      .. " to {star} " ;

-- Get names.
BidManiac_winnerNames = BidManiac_getHighBidNames() ;

outputString = outputString .. BidManiac_winnerNames .. " {star}." ;
if( BidManiac_getNumBids() > 1 ) then
    outputString = "Item " .. BidManiac_itemLink .. " TIED for " .. BidManiac_getMaxBid()
		.. " between " .. BidManiac_winnerNames ;
	BidManiac_Log( "Tied: " .. BidManiac_itemLink .. ", between " .. BidManiac_winnerNames
		.. " for " .. BidManiac_getMaxBid() ) ;
else
	BidManiac_Log( "Sold: " .. BidManiac_itemLink .. ", to " .. BidManiac_winnerNames
		.. " for " .. BidManiac_getMaxBid() ) ;
end

-- Notify the audience of the auction results.
BidManiac_PrintAll( outputString ) ;

end -- BidManiac_auctionSold()

--
-- BidManiac_getHighBidNames()
-- Return a string containing the names of the high bidders, or "" if none exist.
-- The string returned will not have '(' or ')'.
--
function BidManiac_getHighBidNames()
-- BidManiac_Print( "BidManiac_getHighBidNames()" ) ;

BidManiac_winnerNames = "" ;

for user,bid in pairs(BidManiac_bidMatrix) do
    -- If BidManiac_winnerNames is not empty, then there is at least one other winner
    -- Be sure to make it look nice with a comma.
--    BidManiac_Print( "BidManiac_getHighBidNames> user: " .. user .. ", bid: " .. bid ) ;

    if( BidManiac_winnerNames ~= "" ) then
--		BidManiac_Print( "BidManiac_getHighBidNames> Adding comma, BidManiac_winnerNames: "
--			.. BidManiac_winnerNames ) ;
        BidManiac_winnerNames = BidManiac_winnerNames .. ", " ;
    end

    BidManiac_winnerNames = BidManiac_winnerNames .. user ;
--	BidManiac_Print( "BidManiac_getHighBidNames> Updated BidManiac_winnerNames: "
--		.. BidManiac_winnerNames ) ;
end -- for

return BidManiac_winnerNames ;
end -- BidManiac_getHighBidNames

--
-- BidManiac_getBoolString()
-- Return "true" if the arg is true, or "false" otherwise.
--
function BidManiac_getBoolString( someBool )
if( someBool == true ) then
	return "true" ;
end
return "false" ;
end -- BidManiac_getBoolString()

--
-- BidManiac_Log()
-- Add a message to the log frame edit box.
--
function BidManiac_Log( msg )
-- BidManiac_Print( "BidManiac_Log> msg: " .. msg ) ;

-- Be sure to include \r\n so the edit box moves its cursor to
-- the next line.
BidManiac_LogFrameEditBox:Insert( msg .. "\r\n" ) ;
end -- BidManiac_Log()

--
-- BidManiac_allowTieBids()
-- Return true if tie bidding is allowed (min bid increment is 0).
-- Return false otherwise.
--
function BidManiac_allowTieBids()
if( 0 == BidManiac_minBidIncrementSlider:GetValue() ) then
	return true ;
end
return false ;
end -- BidManiac_allowTieBids()

--
-- BidManiac_StripItemLink( itemLink )
-- Strips the link characters from the itemLink, and returns the name in text format,
-- or "" if an error occured.
--
function BidManiac_stripItemLink( itemLink )
if itemLink then
	local _,_,name = string.find( itemLink, "^.*%[(.*)%].*$" ) ;
--	BidManiac_Print( "BidManiac_StripItemLink> Returning: " .. name ) ;
	return name ;
else
	return "" ;
end
end -- BidManiac_StripItemLink()






