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

namespace OcadMapLibrary {

	public class LineTextSymbol : MapSymbol {

		//Doesn't support word space

		MapColorRef textColor;
		public MapColorRef TextColor {
			get {
				return textColor;
			}
			set {
				textColor = value;
			}
		}

		double fontSize;
		public double FontSize {
			get {
				return fontSize;
			}
			set {
				fontSize = value;
			}
		}

		FontFamily fontFamily;
		public FontFamily FontFamily {
			get {
				return fontFamily;
			}
			set {
				fontFamily = value;
			}
		}

		FontStyle style;
		public FontStyle Style {
			get {
				return style;
			}
			set {
				style = value;
			}
		}

		FontWeight weight;
		public FontWeight Weight {
			get {
				return weight;
			}
			set {
				weight = value;
			}
		}

		double characterSpace;
		public double CharacterSpace {
			get {
				return characterSpace;
			}
			set {
				characterSpace = value;
			}
		}

		TextAlignment alignment;
		public TextAlignment Alignment {
			get {
				return alignment;
			}
			set {
				alignment = value;
			}
		}

		FormattedText GetFormattedText(string text, Color color) {
			FormattedText formattedText = new FormattedText(text, new System.Globalization.CultureInfo("en-GB"), FlowDirection.LeftToRight, new Typeface(FontFamily, Style, Weight, FontStretches.Normal), FontSize, new SolidColorBrush(color));
			formattedText.Trimming = TextTrimming.None;
			return formattedText;
		}

		public void DrawSymbol(string text, MapPathFigure data, DrawingContext drawingContext, MapColor mapColor) {
			if (IsHidden) {
				return;
			}
			if (string.IsNullOrWhiteSpace(text)) {
				return;
			}
			if (!TextColor.Matches(mapColor)) {
				return;
			}
			if (!data.HasLength()) {
				return;
			}
			string newText = text;
			if (newText.StartsWith("\r")) {
				newText = newText.Substring(1);
			}
			if (newText.StartsWith("\n")) {
				newText = newText.Substring(1);
			}
			newText = newText.Replace("\t", "");//
			FormattedText formattedText;
			double totalLength = data.GetLength();
			double distance = 0;	
			double extraSpacing = 0;
			double startOffset = 0;
			double absoluteCharacterSpacing = 0;
			if (CharacterSpace != 0) {
				formattedText = GetFormattedText(" ", Colors.Black);
				absoluteCharacterSpacing = formattedText.WidthIncludingTrailingWhitespace * CharacterSpace / 100 * 0.9;//
			}
			if (newText.StartsWith("Winter")) {
				Console.WriteLine("hi");
			}
			double totalTextLength = 0;
			for (int i = 0; i < newText.Length; i++) {
				formattedText = GetFormattedText(newText.Substring(i, 1), Colors.Black);
				double width = formattedText.WidthIncludingTrailingWhitespace * 0.9;//
				totalTextLength += width;
				if (i < newText.Length - 1) {
					totalTextLength += absoluteCharacterSpacing;
				}
			}
			if (Alignment == TextAlignment.Justify) {
				if (newText.Length > 1) {
					extraSpacing = (totalLength - totalTextLength) / (newText.Length - 1);
				} else {
					startOffset = (totalLength - totalTextLength) / 2;
				}
			} else if (Alignment == TextAlignment.Center){
				startOffset = (totalLength - totalTextLength) / 2;
			}else if(Alignment == TextAlignment.Right) {
				startOffset = totalLength - totalTextLength;
			}
			distance = startOffset;
			for (int i = 0; i < newText.Length; i++) {
				formattedText = GetFormattedText(newText.Substring(i, 1), mapColor.Color);
				double textLength = formattedText.WidthIncludingTrailingWhitespace * 0.9;//
				Point newPoint;
				double angle = 0;
				Point? tempPoint = data.GetPointAtLength(distance);
				if (tempPoint == null) {
					newPoint = data.GetEndPoint();
				} else {
					newPoint = tempPoint.Value;
				}
				angle = data.GetAngleAtLength(distance);
				newPoint.Offset(fontSize * Math.Sin(angle), -fontSize * Math.Cos(angle));
				Transform transform = new RotateTransform(angle / Math.PI * 180.0, newPoint.X, newPoint.Y);
				drawingContext.PushTransform(transform);
				drawingContext.DrawText(formattedText, newPoint);
				drawingContext.Pop();
				textLength += absoluteCharacterSpacing;
				distance += textLength;
				distance += extraSpacing;
				if (distance > totalLength) {
					break;
				}
			}
		}

		public Rect GetBoundingRect(string text, MapPathFigure data) {
			//approximation
			if (IsHidden) {
				return Rect.Empty;
			}
			if (string.IsNullOrWhiteSpace(text)) {
				return Rect.Empty;
			}
			if(!data.HasLength()){
				return Rect.Empty;
			}
			Pen pen = new Pen(Brushes.Black, FontSize);
			Geometry geometry = data.GetGeometry();
			return geometry.GetRenderBounds(pen);
		}

	}

}
