//
//	Copyright © 2005 Nemetschek North America 
//	All Rights Reserved.
//
// Created by Vladislav Stanev

#pragma once

namespace VWFC
{
	namespace VWObjects
	{
		// --------------------------------------------------------------------------------------------------
		// wall Component definition structure
		struct SWallComponentInfo {
			InternalName	componentName;
			WorldCoord		width;
			long			componentClass;

			// fill
			CBBoolean		fillUseClass;
			long			fillPat;
			CRGBColor		fillColorFore;
			CRGBColor		fillColorBack;

			// left line
			CBBoolean		penLeftUseClass;
			CBUnsignedByte	penLeftWeight;
			CBSignedByte	penLeftStyle;
			CRGBColor		penLeftColorFore;
			CRGBColor		penLeftColorBack;

			// right line
			CBBoolean		penRightUseClass;
			CBUnsignedByte	penRightWeight;
			CBSignedByte	penRightStyle;
			CRGBColor		penRightColorFore;
			CRGBColor		penRightColorBack;
		};

		// --------------------------------------------------------------------------------------------------
		// symbol break
		struct SWallSymbolBreak {
			size_t				index;
			double				offset;
			SymbolBreakType		symBreak;
		};

		// --------------------------------------------------------------------------------------------------
		// half break
		struct SWallHalfBreak {
			size_t				index;
			double				offset;
			HalfBreakType		halfBreak;
		};

		// --------------------------------------------------------------------------------------------------
		// cap break
		struct SWallCapBreak {
			size_t				index;
			double				offset;
			CapBreakType		capBreak;
		};

		// --------------------------------------------------------------------------------------------------
		// peak break
		struct SWallPeakBreak {
			size_t				index;
			double				offset;
			PeakBreakType		peakBreak;
		};

		// --------------------------------------------------------------------------------------------------
		typedef std::vector<SWallSymbolBreak>		TWallSymbolBreaksArray;
		typedef std::vector<SWallHalfBreak>			TWallHalfBreaksArray;
		typedef std::vector<SWallCapBreak>			TWallCapBreaksArray;
		typedef std::vector<SWallPeakBreak>			TWallPeakBreaksArray;

		// --------------------------------------------------------------------------------------------------
		// interface for wall break listeners
		// use with VWWall::EnumerateWallBreaks(IWallBreakListener*)
		class IWallBreakListener {
		public:
							IWallBreakListener()								{}
			virtual			~IWallBreakListener()								{}
			virtual void	NotifySymbolBreak(const SWallSymbolBreak& )			{}
			virtual void	NotifyHalfBreak(const SWallHalfBreak& )				{}
			virtual void	NotifyCapBreak(const SWallCapBreak& )				{}
			virtual void	NotifyPeakBreak(const SWallPeakBreak& )				{}
		};

		// --------------------------------------------------------------------------------------------------
		class VWWallObj : public VWObject
		{
		public:
								VWWallObj(const VWPoint2D& startPt, const VWPoint2D& endPt, double thickness=0);
								VWWallObj(const VWPoint2D& startPt, const VWPoint2D& ptOnArc, const VWPoint2D& endPt, double thickness=0);
								VWWallObj(const VWLine2D& line, double thickness=0);
								VWWallObj(const VWArc2D& arc, double thickness=0);
								VWWallObj(MCObjectHandle h);
								VWWallObj(const VWWallObj& src);
			virtual				~VWWallObj();

			VWWallObj&			operator=(const VWWallObj& src);

		public:
			VWPoint2D			GetStartPoint() const;
			VWPoint2D			GetEndPoint() const;
			void				GetPoints(VWPoint2D& startPt, VWPoint2D& endPt) const;
			bool				IsRound() const;
			VWArc2D				GetRoundWall() const;
			VWLine2D			GetWall() const;
			bool				IsRoundCCW() const;

			// get composite polygons of the wall. also the polygons of the built-in objects.
			TSTLPolygons2DArray	GetWall2DPolygons_() const;

			// XXX Bobi: causes memory leaks. Should be fixed!!! Use previous function instead 
			// Creates polygon object that is a footprint of the wall. Delete object after using!
			MCObjectHandle		GetWallFootPrint() const;

			// get exact wall footprint - without removing breaks, no object(s) created/modified
			// NB: Straight walls only
			void				GetWallFootPrintEx(VWPolygon2D& footPoly) const;

			// Switch the left and right side of a wall by reversing the direction of the wall.
			// This is an interface to the button with the same name on the Object Info palette.
			void				ReverseSides();

			// Gets/Sets the heights of the start and end of the specified wall.
			// The distances are measured from the ground plane on the layer in which the wall exists.
			void				GetHeights(double& startHeightTop, double& startHeightBottom, double& endHeightTop, double& endHeightBottom) const;
			void				SetHeights(double startHeightTop, double startHeightBottom, double endHeightTop, double endHeightBottom);
			double				GetStartHeightTop() const;
			double				GetStartHeightBottom() const;

			// The width of the wall.
			double				GetWidth() const;
			void				SetWidth(double width);

			// Available in VW Architect only. Moves the wall perpendiclar to its definition line by the specified offset,
			// and maintains all wall connections Offsets to the left hand side of the wall are positive, and to the right hand side are negative.
			void				MoveByOffset(double& offset);

			// COMPONENTS
			size_t				GetComponentCount() const;
			SWallComponentInfo	GetComponentInfo(size_t index) const;
			void				SetComponentInfo(size_t index, const SWallComponentInfo& info);
			bool				InsertNewComponent(size_t beforeIndex, const SWallComponentInfo& info);
			bool				DeleteComponent(size_t index);

			// BREAKS
			void				EnumerateBreaks(IWallBreakListener* pBreakListener) const;
			void				EnumerateBreaks(TWallSymbolBreaksArray& outArrSymbolBreaks) const;
			void				EnumerateBreaks(TWallHalfBreaksArray& outArrHalfBreaks) const;
			void				EnumerateBreaks(TWallCapBreaksArray& outArrCapBreaks) const;
			void				EnumerateBreaks(TWallPeakBreaksArray& outArrPeakBreaks) const;
			size_t				AddBreak(const SWallSymbolBreak& brk);
			size_t				AddBreak(const SWallHalfBreak& brk);
			size_t				AddBreak(const SWallCapBreak& brk);
			size_t				AddBreak(const SWallPeakBreak& brk);
			void				DeleteBreak(size_t index);

		// tool
		public:
			// Return true if the specified object handle is wall
			static bool			IsWallObject(MCObjectHandle hObj);

		private:
			static Boolean		GetAllBreaksCallback(MCObjectHandle, long index, double off, long breakType, void* breakData, CallBackPtr , void* env);
			void				GetWall2DPolygons(const VWTransformMatrix& theMat, MCObjectHandle hGroup, TSTLPolygons2DArray& polygonArr) const;

		private:
		};
	}
}