function WindCasting_OnLoad(unit, showTradeSkills)
	WindCommon_setBackground(WindCastingBorder, WindCasting, 6);

	this:RegisterEvent("VARIABLES_LOADED");
	this:RegisterEvent("UNIT_SPELLCAST_START");
	this:RegisterEvent("UNIT_SPELLCAST_STOP");
	this:RegisterEvent("UNIT_SPELLCAST_FAILED");
	this:RegisterEvent("UNIT_SPELLCAST_INTERRUPTED");
	this:RegisterEvent("UNIT_SPELLCAST_DELAYED");
	this:RegisterEvent("UNIT_SPELLCAST_CHANNEL_START");
	this:RegisterEvent("UNIT_SPELLCAST_CHANNEL_UPDATE");
	this:RegisterEvent("UNIT_SPELLCAST_CHANNEL_STOP");
	this:RegisterEvent("PLAYER_ENTERING_WORLD");

	this.unit = unit; 
	this.showTradeSkills = showTradeSkills; 
	this.casting = nil;
	this.channeling = nil;
	this.holdTime = 0;
	this.showCastbar = true;

	WindCastingIcon:Hide(); 

	CastingBarFrame:UnregisterAllEvents();
	CastingBarFrame:SetScript("OnLoad", nil);
	CastingBarFrame:SetScript("OnEvent", nil);
	CastingBarFrame:SetScript("OnUpdate", nil);
	CastingBarFrame:Hide();

end

function WindCasting_OnEvent(newevent, newarg1)
	if ( newevent == "VARIABLES_LOADED" ) then
		WindCasting_initConfig();
		WindCasting_setPoint();
		WindCasting_setScale();
		WindCasting_setSize();
		WindCasting_setColor();
	end
	if ( newevent == "PLAYER_ENTERING_WORLD" ) then
		local nameChannel  = UnitChannelInfo(this.unit);
		local nameSpell  = UnitCastingInfo(this.unit);
		if ( nameChannel ) then
			newevent = "UNIT_SPELLCAST_CHANNEL_START";
			newarg1 = this.unit;
		elseif ( nameSpell ) then
			newevent = "UNIT_SPELLCAST_START";
			newarg1 = this.unit;
		end
	end
	if ( newarg1 ~= this.unit ) then
		return;
	end
	if ( newevent == "UNIT_SPELLCAST_START" ) then WindCasting_spellStart(WindCasting);
	elseif ( newevent == "UNIT_SPELLCAST_STOP" or newevent == "UNIT_SPELLCAST_CHANNEL_STOP" ) then WindCasting_spellStop(WindCasting, newevent);
	elseif ( newevent == "UNIT_SPELLCAST_FAILED" or newevent == "UNIT_SPELLCAST_INTERRUPTED" ) then WindCasting_spellFail(WindCasting, newevent);
	elseif ( newevent == "UNIT_SPELLCAST_DELAYED" ) then WindCasting_spellDelay(WindCasting);
	elseif ( newevent == "UNIT_SPELLCAST_CHANNEL_START" ) then WindCasting_channelStart(WindCasting);
	elseif ( newevent == "UNIT_SPELLCAST_CHANNEL_UPDATE" ) then WindCasting_channelUpdate(WindCasting); end
end

function WindCasting_spellStart(obj)
	local name, nameSubtext, text, texture, startTime, endTime, isTradeSkill = UnitCastingInfo(obj.unit);
	local label;

	if( nameSubtext and nameSubtext ~= "" ) then 
		label = name.." ("..nameSubtext..")"; 
	else 
		label = name; 
	end

	if ( not name or (not obj.showTradeSkills and isTradeSkill)) then
		obj:Hide();
		return;
	end
	obj:SetStatusBarColor(1.0, 0.7, 0.0);
	WindCastingSpark:Show();
	obj.startTime = startTime / 1000;
	obj.maxValue = endTime / 1000;
	obj:SetMinMaxValues(obj.startTime, obj.maxValue);
	obj:SetValue(obj.startTime);
	WindCastingText:SetText(label);
	WindCastingIcon:SetTexture(texture);
	obj:SetAlpha(1.0);
	obj.holdTime = 0;
	obj.casting = 1;
	obj.channeling = nil;
	obj.fadeOut = nil;
	if ( this.showCastbar ) then
		obj:Show();
		WindCastingBorder:Show();
		WindCastingIcon:Show();
	end
end

function WindCasting_spellStop(obj, newevent)
	if ( not obj:IsVisible() ) then
		obj:Hide();
		WindCastingBorder:Hide();
	end
	if ( obj:IsShown() ) then
		WindCastingSpark:Hide();
		obj:SetValue(obj.maxValue);
		if ( newevent == "UNIT_SPELLCAST_STOP" ) then
			obj:SetStatusBarColor(0.0, 1.0, 0.0);
			obj.casting = nil;
		else
			obj.channeling = nil;
		end
		obj.fadeOut = 1;
		obj.holdTime = 0;
	end
end

function WindCasting_spellFail(obj, newevent)
	if ( obj:IsShown() and not obj.channeling ) then
		obj:SetValue(obj.maxValue);
		obj:SetStatusBarColor(1.0, 0.0, 0.0);
		WindCastingSpark:Hide();
		if ( newevent == "UNIT_SPELLCAST_FAILED" ) then
			WindCastingText:SetText(FAILED);
		else
			WindCastingText:SetText(INTERRUPTED);
		end
		obj.casting = nil;
		obj.channeling = nil;
		obj.fadeOut = 1;
		obj.holdTime = GetTime() + CASTING_BAR_HOLD_TIME;
	end
end

function WindCasting_spellDelay(obj)
	if ( obj:IsShown() ) then
		local name, nameSubtext, text, texture, startTime, endTime, isTradeSkill = UnitCastingInfo(obj.unit);
		if ( not name or (not obj.showTradeSkills and isTradeSkill)) then
			obj:Hide();
			return;
		end
		obj.startTime = startTime / 1000;
		obj.maxValue = endTime / 1000;
		obj:SetMinMaxValues(obj.startTime, obj.maxValue);
	end
end

function WindCasting_channelStart(obj)
	local name, nameSubtext, text, texture, startTime, endTime, isTradeSkill = UnitChannelInfo(obj.unit);
	local label;

	if( nameSubtext and nameSubtext ~= "" ) then 
		label = name.." ("..nameSubtext..")"; 
	else 
		label = name; 
	end

	if ( not name or (not obj.showTradeSkills and isTradeSkill)) then
		obj:Hide();
		return;
	end
	obj:SetStatusBarColor(0.0, 1.0, 0.0);
	WindCastingSpark:Show();
	obj.startTime = startTime / 1000;
	obj.endTime = endTime / 1000;
	obj.duration = obj.endTime - obj.startTime;
	obj.maxValue = obj.startTime;
	obj:SetMinMaxValues(obj.startTime, obj.endTime);
	obj:SetValue(obj.endTime);
	WindCastingText:SetText(label);
	WindCastingIcon:SetTexture(texture);
	obj:SetAlpha(1.0);
	obj.holdTime = 0;
	obj.casting = nil;
	obj.channeling = 1;
	obj.fadeOut = nil;
	if ( obj.showCastbar ) then
		obj:Show();
		WindCastingBorder:Show();
		WindCastingIcon:Show();
	end
end

function WindCasting_channelUpdate(obj)
	if ( obj:IsShown() ) then
		local name, nameSubtext, text, texture, startTime, endTime, isTradeSkill = UnitChannelInfo(obj.unit);
		if ( not name or (not obj.showTradeSkills and isTradeSkill)) then
			obj:Hide();
			return;
		end
		obj.startTime = startTime / 1000;
		obj.endTime = endTime / 1000;
		obj.maxValue = obj.startTime;
		obj:SetMinMaxValues(obj.startTime, obj.endTime);
	end
end

function WindCasting_OnUpdate()
	if ( WindCasting.casting ) then WindCasting_casting(WindCasting);
	elseif ( WindCasting.channeling ) then WindCasting_channeling(WindCasting);
	elseif ( GetTime() < WindCasting.holdTime ) then return;
	elseif ( WindCasting.fadeOut ) then WindCasting_fadeOut(WindCasting); end
end

function WindCasting_casting(obj)
	local status = GetTime();
	if ( status > obj.maxValue ) then status = obj.maxValue; end
	if ( status == obj.maxValue ) then
		obj:SetValue(obj.maxValue);
		obj:SetStatusBarColor(0.0, 1.0, 0.0);
		WindCastingSpark:Hide();
		obj.casting = nil;
		obj.fadeOut = 1;
		return;
	end
	obj:SetValue(status);
	local sparkPosition = ((status - obj.startTime) / (obj.maxValue - obj.startTime)) * WindCastingConfigAll[5];
	if ( sparkPosition < 0 ) then sparkPosition = 0; end
	WindCastingTime:SetText(string.format("%.1f", math.max(obj.maxValue - status, 0.0)));
	WindCastingSpark:SetPoint("CENTER", obj, "LEFT", sparkPosition, 0);
end

function WindCasting_channeling(obj)
	local time = GetTime();
	if ( time > obj.endTime ) then time = obj.endTime; end
	if ( time == obj.endTime ) then
		obj:SetStatusBarColor(0.0, 1.0, 0.0);
		WindCastingSpark:Hide();
		obj.channeling = nil;
		obj.fadeOut = 1;
		return;
	end
	local barValue = obj.startTime + (obj.endTime - time);
	obj:SetValue( barValue );
	local sparkPosition = ((barValue - obj.startTime) / (obj.endTime - obj.startTime)) * WindCastingConfigAll[5];
	WindCastingTime:SetText(string.format("%.1f", math.max(obj.endTime - time, 0.0)));
	WindCastingSpark:SetPoint("CENTER", obj, "LEFT", sparkPosition, 0);
end

function WindCasting_fadeOut(obj)
	local alpha = obj:GetAlpha() - CASTING_BAR_ALPHA_STEP;
	if ( alpha > 0 ) then obj:SetAlpha(alpha);
	else
		obj.fadeOut = nil;
		obj:Hide();
		WindCastingBorder:Hide();
		WindCastingIcon:Hide();
	end
end

function WindCasting_initConfig()
	if (not WindCastingConfigAll) then WindCastingConfigAll = WindCastingDefault; end

	if (IsAddOnLoaded("WindConfig")) then 
		WindCastingConfig_OnShow();
		WindCastingConfigBody_setColor(color); 
	end
end

function WindCasting_setPoint()
	WindCommon_setPoint(WindCasting, WindCastingConfigAll[1], UIParent, WindCastingConfigAll[1], WindCastingConfigAll[2], WindCastingConfigAll[3]);
end

function WindCasting_setScale()
	WindCasting:SetScale(WindCastingConfigAll[4]);
end

function WindCasting_setSize()
	WindCommon_setSize(WindCasting, WindCastingConfigAll[5], WindCastingConfigAll[6]);
end

function WindCasting_setColor()
	WindCastingBorder:SetBackdropBorderColor(WindCastingConfigAll[7][1].r, WindCastingConfigAll[7][1].g, WindCastingConfigAll[7][1].b, WindCastingConfigAll[7][1].a);
	WindCastingBorder:SetBackdropColor(WindCastingConfigAll[7][2].r, WindCastingConfigAll[7][2].g, WindCastingConfigAll[7][2].b, WindCastingConfigAll[7][2].a);
	if (WindCastingConfigBorder) then WindCastingConfigBorder:SetBackdropBorderColor(WindCastingConfigAll[7][1].r, WindCastingConfigAll[7][1].g, WindCastingConfigAll[7][1].b, WindCastingConfigAll[7][1].a);
	WindCastingConfigBorder:SetBackdropColor(WindCastingConfigAll[7][2].r, WindCastingConfigAll[7][2].g, WindCastingConfigAll[7][2].b, WindCastingConfigAll[7][2].a); end
end

function WindCasting_resetColor()
	WindCastingConfigAll[7] = WindCastingDefault[7];
	WindCasting_setColor();
end
