using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Media;
using System.Windows;

namespace OcadMapLibrary {

	public class AreaSymbol : MapSymbol {

		public AreaSymbol() {
		}

		MapColorRef fillColor;
		public MapColorRef FillColor {
			get {
				return fillColor;
			}
			set {
				fillColor = value;
			}
		}

		MapHatchInfo hatching1;
		public MapHatchInfo Hatching1 {
			get {
				return hatching1;
			}
			set {
				hatching1 = value;
			}
		}

		MapHatchInfo hatching2;
		public MapHatchInfo Hatching2 {
			get {
				return hatching2;
			}
			set {
				hatching2 = value;
			}
		}

		MapTileInfo tileInfo;
		public MapTileInfo TileInfo {
			get {
				return tileInfo;
			}
			set {
				tileInfo = value;
			}
		}

		public void DrawSymbol(MapAreaGeometry data, double fillRotation, DrawingContext drawingContext, MapColor mapColor) {
			if (IsHidden) {
				return;
			}
			if (!data.MainFigure.HasLength()) {
				return;
			}
			DrawMainFill(data, drawingContext, mapColor);
			DrawHatching(data, fillRotation, hatching1, drawingContext, mapColor);
			DrawHatching(data, fillRotation, hatching2, drawingContext, mapColor);
			DrawTile(data, fillRotation, drawingContext, mapColor);
		}

		void DrawMainFill(MapAreaGeometry data, DrawingContext drawingContext, MapColor mapColor) {
			if (FillColor == null) {
				return;
			}
			if (!FillColor.Matches(mapColor)) {
				return;
			}
			Geometry geometry = data.GetGeometry();
			Brush brush = new SolidColorBrush(mapColor.Color);
			drawingContext.DrawGeometry(brush, null, geometry);
		}

		void DrawHatching(MapAreaGeometry data, double fillRotation, MapHatchInfo hatching, DrawingContext drawingContext, MapColor mapColor) {
			if (hatching == null) {
				return;
			}
			if (!hatching.Color.Matches(mapColor)) {
				return;
			}
			Geometry geometry = data.GetGeometry();
			double width;
			width = hatching.HatchSpacing;
			if (width <= 0) {
				return;
			}
			RotateTransform hatchRotate = new RotateTransform(hatching.HatchAngle + fillRotation);
			drawingContext.PushClip(geometry);
			drawingContext.PushTransform(hatchRotate);
			Rect rect = geometry.Bounds;
			Rect newRect = rect;
			newRect = hatchRotate.Inverse.TransformBounds(rect);
			Pen pen = new Pen(new SolidColorBrush(mapColor.Color), hatching.StrokeThickness);
			double extraXOffset = 0;
			int num = (int)Math.Round(newRect.Left / width);
			extraXOffset = width * num - newRect.Left;
			for (double xPos = newRect.Left + extraXOffset; xPos <= newRect.Right + hatching.StrokeThickness / 2; xPos += width) {
				drawingContext.DrawLine(pen, new Point(xPos, newRect.Top), new Point(xPos, newRect.Bottom));
			}
			drawingContext.Pop();
			drawingContext.Pop();
		}

		void DrawTile(MapAreaGeometry data, double fillRotation, DrawingContext drawingContext, MapColor mapColor) {
			if (tileInfo == null) {
				return;
			}
			if (tileInfo.TileSymbol == null || tileInfo.TileMode == MapTileMode.None) {
				return;
			}
			if (!tileInfo.TileSymbol.ContainsColor(mapColor)) {
				return;
			}
			Geometry geometry = data.GetGeometry();
			//DrawingGroup tileDrawing = new DrawingGroup();
			//DrawingContext groupContext = tileDrawing.Open();
			//tileInfo.TileSymbol.DrawSymbol(groupContext, mapColor);
			//groupContext.Close();
			//DrawingGroup drawingBufferGroup = new DrawingGroup();
			//DrawingContext drawingBuffer = drawingBufferGroup.Open();
			//drawingBuffer.PushClip(geometry);
			drawingContext.PushClip(geometry);
			Rect rect = geometry.Bounds;
			Rect newRect = rect;
			double newRotation = tileInfo.Rotation + fillRotation;
			if (newRotation != 0) {
				RotateTransform inverse = new RotateTransform(-newRotation);
				Geometry transformedData = geometry.Clone();
				transformedData.Transform = inverse;
				newRect = transformedData.Bounds;
			}
			Rect targetRect = tileInfo.TileSymbol.GetBoundingRect(new Point(0, 0));
			double width;
			width = tileInfo.TileWidth;
			double height;
			height = tileInfo.TileHeight;
			RotateTransform rotate = null;
			if (newRotation != 0) {
				rotate = new RotateTransform(newRotation);
				//drawingBuffer.PushTransform(rotate);
				drawingContext.PushTransform(rotate);
			}
			double xOffset = -targetRect.Left;
			double yOffset = -targetRect.Top;
			double extraXOffset = 0;
			double extraYOffset = 0;
			int num;
			num = (int)Math.Round(newRect.Left / width);
			extraXOffset = width * num - newRect.Left;
			num = (int)Math.Round(newRect.Top / height);
			extraYOffset = height * num - newRect.Top;
			int row = 0;
			for (double yPos = newRect.Top + extraYOffset; yPos <= newRect.Bottom; yPos += height) {
				double extraOffset = 0;
				if (row == 1 && tileInfo.TileMode == MapTileMode.Honeycomb) {
					extraOffset = -width / 2;
				}
				for (double xPos = newRect.Left + extraOffset + extraXOffset; xPos <= newRect.Right; xPos += width) {
					Rect currentBounds = new Rect(xPos + xOffset, yPos + yOffset, targetRect.Width, targetRect.Height);
					if (rotate != null) {
						currentBounds = rotate.TransformBounds(currentBounds);
					}
					if (Rect.Intersect(currentBounds, rect) == Rect.Empty) {
						continue;
					}
					TranslateTransform translate = new TranslateTransform(xPos + xOffset, yPos + yOffset);
					//drawingBuffer.PushTransform(translate);
					//drawingBuffer.DrawDrawing(tileDrawing);
					//drawingBuffer.Pop();
					drawingContext.PushTransform(translate);
					tileInfo.TileSymbol.DrawSymbol(drawingContext, mapColor);
					drawingContext.Pop();
				}
				row++;
				if (row >= 2) {
					row = 0;
				}
			}
			if (newRotation != 0) {
				//drawingBuffer.Pop();
				drawingContext.Pop();
			}
			//drawingBuffer.Pop();
			drawingContext.Pop();
			//drawingBuffer.Close();
			//drawingContext.DrawDrawing(drawingBufferGroup);
		}

		public Rect GetBoundingRect(MapAreaGeometry data) {
			Rect rect = Rect.Empty;
			if (IsHidden) {
				return rect;
			}
			if (!data.MainFigure.HasLength()) {
				return rect;
			}
			Geometry geometry = data.GetGeometry();
			return geometry.Bounds;
		}

	}

}
