using System;
using System.Runtime.InteropServices;

namespace CPF.Mac.CoreGraphics
{
	public struct CGAffineTransform
	{
		public double xx;

		public double yx;

		public double xy;

		public double yy;

		public double x0;

		public double y0;

		public bool IsIdentity
		{
			get
			{
				if (xx == 1.0 && yx == 0.0 && xy == 0.0 && yy == 1.0 && x0 == 0.0)
				{
					return y0 == 0.0;
				}
				return false;
			}
		}

		public CGAffineTransform(double xx, double yx, double xy, double yy, double x0, double y0)
		{
			this.xx = xx;
			this.yx = yx;
			this.xy = xy;
			this.yy = yy;
			this.x0 = x0;
			this.y0 = y0;
		}

		public static CGAffineTransform MakeIdentity()
		{
			return new CGAffineTransform(1.0, 0.0, 0.0, 1.0, 0.0, 0.0);
		}

		public static CGAffineTransform MakeRotation(double angle)
		{
			return new CGAffineTransform(Math.Cos(angle), Math.Sin(angle), 0.0 - Math.Sin(angle), Math.Cos(angle), 0.0, 0.0);
		}

		public static CGAffineTransform MakeScale(double sx, double sy)
		{
			return new CGAffineTransform(sx, 0.0, 0.0, sy, 0.0, 0.0);
		}

		public static CGAffineTransform MakeTranslation(double tx, double ty)
		{
			return new CGAffineTransform(1.0, 0.0, 0.0, 1.0, tx, ty);
		}

		public static CGAffineTransform Multiply(CGAffineTransform a, CGAffineTransform b)
		{
			return new CGAffineTransform(a.xx * b.xx + a.yx * b.xy, a.xx * b.yx + a.yx * b.yy, a.xy * b.xx + a.yy * b.xy, a.xy * b.yx + a.yy * b.yy, a.x0 * b.xx + a.y0 * b.xy + b.x0, a.x0 * b.yx + a.y0 * b.yy + b.y0);
		}

		public void Multiply(CGAffineTransform b)
		{
			CGAffineTransform cGAffineTransform = this;
			xx = cGAffineTransform.xx * b.xx + cGAffineTransform.yx * b.xy;
			yx = cGAffineTransform.xx * b.yx + cGAffineTransform.yx * b.yy;
			xy = cGAffineTransform.xy * b.xx + cGAffineTransform.yy * b.xy;
			yy = cGAffineTransform.xy * b.yx + cGAffineTransform.yy * b.yy;
			x0 = cGAffineTransform.x0 * b.xx + cGAffineTransform.y0 * b.xy + b.x0;
			y0 = cGAffineTransform.x0 * b.yx + cGAffineTransform.y0 * b.yy + b.y0;
		}

		public void Scale(double sx, double sy)
		{
			Multiply(MakeScale(sx, sy));
		}

		public void Translate(double tx, double ty)
		{
			Multiply(MakeTranslation(tx, ty));
		}

		public void Rotate(double angle)
		{
			Multiply(MakeRotation(angle));
		}

		public override string ToString()
		{
			return $"xx:{xx:##0.0#} yx:{yx:##0.0#} xy:{xy:##0.0#} yy:{yy:##0.0#} x0:{x0:##0.0#} y0:{y0:##0.0#}";
		}

		public static bool operator ==(CGAffineTransform lhs, CGAffineTransform rhs)
		{
			if (lhs.xx == rhs.xx && lhs.xy == rhs.xy && lhs.yx == rhs.yx && lhs.yy == rhs.yy && lhs.x0 == rhs.x0)
			{
				return lhs.y0 == rhs.y0;
			}
			return false;
		}

		public static bool operator !=(CGAffineTransform lhs, CGAffineTransform rhs)
		{
			return !(lhs == rhs);
		}

		public static CGAffineTransform operator *(CGAffineTransform a, CGAffineTransform b)
		{
			return new CGAffineTransform(a.xx * b.xx + a.yx * b.xy, a.xx * b.yx + a.yx * b.yy, a.xy * b.xx + a.yy * b.xy, a.xy * b.yx + a.yy * b.yy, a.x0 * b.xx + a.y0 * b.xy + b.x0, a.x0 * b.yx + a.y0 * b.yy + b.y0);
		}

		public override bool Equals(object o)
		{
			if (!(o is CGAffineTransform))
			{
				return false;
			}
			return this == (CGAffineTransform)o;
		}

		public override int GetHashCode()
		{
			return (int)xx ^ (int)xy ^ (int)yx ^ (int)yy ^ (int)x0 ^ (int)y0;
		}

		public CGPoint TransformPoint(CGPoint point)
		{
			return new CGPoint(xx * point.X + xy * point.Y + x0, yx * point.X + yy * point.Y + y0);
		}

		[DllImport("/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/CoreGraphics")]
		public static extern CGRect CGRectApplyAffineTransform(CGRect rect, CGAffineTransform t);

		public CGRect TransformRect(CGRect rect)
		{
			return CGRectApplyAffineTransform(rect, this);
		}

		[DllImport("/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/CoreGraphics.framework/CoreGraphics")]
		public static extern CGAffineTransform CGAffineTransformInvert(CGAffineTransform t);

		public CGAffineTransform Invert()
		{
			return CGAffineTransformInvert(this);
		}
	}
}
