﻿// Decompiled with JetBrains decompiler
// Type: InvokedServer.Controls.HexEditor.HexViewHandler
// Assembly: HQ, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: C53BC0E5-A85B-41E9-8105-FC74ED122A9A
// Assembly location: C:\Users\ian\Downloads\Telegram Desktop\fein\HQ.exe

using System;
using System.Drawing;
using System.Windows.Forms;


namespace InvokedServer.Controls.HexEditor
{
	public class HexViewHandler
	{
		private bool _isEditing;
		private string _hexType = "X2";
		private Rectangle _recHexValue;
		private StringFormat _stringFormat;
		private InvokedServer.Controls.HexEditor.HexEditor _editor;

		public int MaxWidth
		{
			get => this._recHexValue.X + this._recHexValue.Width * this._editor.BytesPerLine;
		}

		public HexViewHandler(InvokedServer.Controls.HexEditor.HexEditor editor)
		{
			this._editor = editor;
			this._stringFormat = new StringFormat(StringFormat.GenericTypographic);
			this._stringFormat.Alignment = StringAlignment.Center;
			this._stringFormat.LineAlignment = StringAlignment.Center;
		}

		public void OnKeyPress(KeyPressEventArgs e)
		{
			if (!this.IsHex(e.KeyChar))
				return;
			this.HandleUserInput(e.KeyChar);
		}

		public void OnKeyDown(KeyEventArgs e)
		{
			if (e.KeyCode == Keys.Delete || e.KeyCode == Keys.Back)
			{
				if (this._editor.SelectionLength > 0)
				{
					this.HandleUserRemove();
					int caretIndex = this._editor.CaretIndex;
					Point caretLocation = this.GetCaretLocation(caretIndex);
					this._editor.SetCaretStart(caretIndex, caretLocation);
				}
				else if (this._editor.CaretIndex < this._editor.LastVisibleByte && e.KeyCode == Keys.Delete)
				{
					this._editor.RemoveByteAt(this._editor.CaretIndex);
					this._editor.SetCaretStart(this._editor.CaretIndex, this.GetCaretLocation(this._editor.CaretIndex));
				}
				else if (this._editor.CaretIndex > 0 && e.KeyCode == Keys.Back)
				{
					int index = this._editor.CaretIndex - 1;
					if (this._isEditing)
						index = this._editor.CaretIndex;
					this._editor.RemoveByteAt(index);
					Point caretLocation = this.GetCaretLocation(index);
					this._editor.SetCaretStart(index, caretLocation);
				}
				this._isEditing = false;
			}
			else if (e.KeyCode == Keys.Up && this._editor.CaretIndex - this._editor.BytesPerLine >= 0)
			{
				int index = this._editor.CaretIndex - this._editor.BytesPerLine;
				if (index % this._editor.BytesPerLine == 0 && this._editor.CaretPosX >= this._recHexValue.X + this._recHexValue.Width * this._editor.BytesPerLine)
				{
					Point location = new Point(this._editor.CaretPosX, this._editor.CaretPosY - this._recHexValue.Height);
					if (index == 0)
					{
						location = new Point(this._editor.CaretPosX, this._editor.CaretPosY);
						index = this._editor.BytesPerLine;
					}
					if (e.Shift)
						this._editor.SetCaretEnd(index, location);
					else
						this._editor.SetCaretStart(index, location);
					this._isEditing = false;
				}
				else
					this.HandleArrowKeys(index, e.Shift);
			}
			else if (e.KeyCode == Keys.Down && (this._editor.CaretIndex - 1) / this._editor.BytesPerLine < this._editor.HexTableLength / this._editor.BytesPerLine)
			{
				int index = this._editor.CaretIndex + this._editor.BytesPerLine;
				if (index > this._editor.HexTableLength)
				{
					this.HandleArrowKeys(this._editor.HexTableLength, e.Shift);
				}
				else
				{
					Point location = new Point(this._editor.CaretPosX, this._editor.CaretPosY + this._recHexValue.Height);
					if (e.Shift)
						this._editor.SetCaretEnd(index, location);
					else
						this._editor.SetCaretStart(index, location);
					this._isEditing = false;
				}
			}
			else if (e.KeyCode == Keys.Left && this._editor.CaretIndex - 1 >= 0)
			{
				this.HandleArrowKeys(this._editor.CaretIndex - 1, e.Shift);
			}
			else
			{
				if (e.KeyCode != Keys.Right || this._editor.CaretIndex + 1 > this._editor.HexTableLength)
					return;
				this.HandleArrowKeys(this._editor.CaretIndex + 1, e.Shift);
			}
		}

		public void HandleArrowKeys(int index, bool isShiftDown)
		{
			Point caretLocation = this.GetCaretLocation(index);
			if (isShiftDown)
				this._editor.SetCaretEnd(index, caretLocation);
			else
				this._editor.SetCaretStart(index, caretLocation);
			this._isEditing = false;
		}

		public void OnMouseDown(int x, int y)
		{
			int num1 = (x - this._recHexValue.X) / this._recHexValue.Width;
			int num2 = (y - this._recHexValue.Y) / this._recHexValue.Height;
			int num3 = num1 > this._editor.BytesPerLine ? this._editor.BytesPerLine : num1;
			int num4 = num3 < 0 ? 0 : num3;
			int num5 = num2 > this._editor.MaxBytesV ? this._editor.MaxBytesV : num2;
			int num6 = num5 < 0 ? 0 : num5;
			if ((this._editor.LastVisibleByte - this._editor.FirstVisibleByte) / this._editor.BytesPerLine <= num6)
			{
				if ((this._editor.LastVisibleByte - this._editor.FirstVisibleByte) % this._editor.BytesPerLine <= num4)
					num4 = (this._editor.LastVisibleByte - this._editor.FirstVisibleByte) % this._editor.BytesPerLine;
				num6 = (this._editor.LastVisibleByte - this._editor.FirstVisibleByte) / this._editor.BytesPerLine;
			}
			this._editor.SetCaretStart(Math.Min(this._editor.LastVisibleByte, this._editor.FirstVisibleByte + num4 + num6 * this._editor.BytesPerLine), new Point(num4 * this._recHexValue.Width + this._recHexValue.X, num6 * this._recHexValue.Height + this._recHexValue.Y));
			this._isEditing = false;
		}

		public void OnMouseDragged(int x, int y)
		{
			int num1 = (x - this._recHexValue.X) / this._recHexValue.Width;
			int num2 = (y - this._recHexValue.Y) / this._recHexValue.Height;
			int num3 = num1 > this._editor.BytesPerLine ? this._editor.BytesPerLine : num1;
			int num4 = num3 < 0 ? 0 : num3;
			int num5 = num2 > this._editor.MaxBytesV ? this._editor.MaxBytesV : num2;
			int num6 = this._editor.FirstVisibleByte <= 0 ? (num5 < 0 ? 0 : num5) : (num5 < 0 ? -1 : num5);
			if ((this._editor.LastVisibleByte - this._editor.FirstVisibleByte) / this._editor.BytesPerLine <= num6)
			{
				if ((this._editor.LastVisibleByte - this._editor.FirstVisibleByte) % this._editor.BytesPerLine <= num4)
					num4 = (this._editor.LastVisibleByte - this._editor.FirstVisibleByte) % this._editor.BytesPerLine;
				num6 = (this._editor.LastVisibleByte - this._editor.FirstVisibleByte) / this._editor.BytesPerLine;
			}
			this._editor.SetCaretEnd(Math.Min(this._editor.LastVisibleByte, this._editor.FirstVisibleByte + num4 + num6 * this._editor.BytesPerLine), new Point(num4 * this._recHexValue.Width + this._recHexValue.X, num6 * this._recHexValue.Height + this._recHexValue.Y));
		}

		public void OnMouseDoubleClick()
		{
			if (this._editor.CaretIndex >= this._editor.LastVisibleByte)
				return;
			int index = this._editor.CaretIndex + 1;
			Point caretLocation = this.GetCaretLocation(index);
			this._editor.SetCaretEnd(index, caretLocation);
		}

		public void Update(int startPositionX, Rectangle area)
		{
			int x = startPositionX;
			int y = area.Y;
			SizeF charSize = this._editor.CharSize;
			int width = (int)((double)charSize.Width * 3.0);
			charSize = this._editor.CharSize;
			int height = (int)charSize.Height - 2;
			this._recHexValue = new Rectangle(x, y, width, height);
			this._recHexValue.X += this._editor.EntityMargin;
		}

		public void Paint(Graphics g, int index, int startIndex)
		{
			Point byteColumnAndRow = this.GetByteColumnAndRow(index);
			if (this._editor.IsSelected(index + startIndex))
				this.PaintByteAsSelected(g, byteColumnAndRow, index + startIndex);
			else
				this.PaintByte(g, byteColumnAndRow, index + startIndex);
		}

		private void PaintByteAsSelected(Graphics g, Point point, int index)
		{
			SolidBrush solidBrush1 = new SolidBrush(this._editor.SelectionBackColor);
			SolidBrush solidBrush2 = new SolidBrush(this._editor.SelectionForeColor);
			RectangleF bound = this.GetBound(point);
			string s = this._editor.GetByte(index).ToString(this._hexType);
			g.FillRectangle((Brush)solidBrush1, bound);
			g.DrawString(s, this._editor.Font, (Brush)solidBrush2, bound, this._stringFormat);
		}

		private void PaintByte(Graphics g, Point point, int index)
		{
			SolidBrush solidBrush = new SolidBrush(this._editor.ForeColor);
			RectangleF bound = this.GetBound(point);
			string s = this._editor.GetByte(index).ToString(this._hexType);
			g.DrawString(s, this._editor.Font, (Brush)solidBrush, bound, this._stringFormat);
		}

		public void SetLowerCase() => this._hexType = "x2";

		public void SetUpperCase() => this._hexType = "X2";

		public void Focus()
		{
			int caretIndex = this._editor.CaretIndex;
			Point caretLocation = this.GetCaretLocation(caretIndex);
			this._editor.SetCaretStart(caretIndex, caretLocation);
		}

		private Point GetCaretLocation(int index)
		{
			return new Point(this._recHexValue.X + this._recHexValue.Width * (index % this._editor.BytesPerLine), this._recHexValue.Y + this._recHexValue.Height * ((index - (this._editor.FirstVisibleByte + index % this._editor.BytesPerLine)) / this._editor.BytesPerLine));
		}

		private void HandleUserRemove()
		{
			int selectionStart = this._editor.SelectionStart;
			Point caretLocation = this.GetCaretLocation(selectionStart);
			this._editor.RemoveSelectedBytes();
			this._editor.SetCaretStart(selectionStart, caretLocation);
		}

		private void HandleUserInput(char key)
		{
			if (!this._editor.CaretFocused)
				return;
			this.HandleUserRemove();
			if (this._isEditing)
			{
				this._isEditing = false;
				this._editor.SetByte(this._editor.CaretIndex, (byte)((uint)this._editor.GetByte(this._editor.CaretIndex) + (uint)Convert.ToByte(key.ToString(), 16)));
				int index = this._editor.CaretIndex + 1;
				Point caretLocation = this.GetCaretLocation(index);
				this._editor.SetCaretStart(index, caretLocation);
			}
			else
			{
				this._isEditing = true;
				byte num = Convert.ToByte(key.ToString() + "0", 16);
				if (this._editor.HexTable.Length == 0)
					this._editor.AppendByte(num);
				else
					this._editor.InsertByte(this._editor.CaretIndex, num);
				this._editor.SetCaretStart(this._editor.CaretIndex, new Point(this._recHexValue.X + this._recHexValue.Width * (this._editor.CaretIndex % this._editor.BytesPerLine) + this._recHexValue.Width / 2, this._recHexValue.Y + this._recHexValue.Height * ((this._editor.CaretIndex - (this._editor.FirstVisibleByte + this._editor.CaretIndex % this._editor.BytesPerLine)) / this._editor.BytesPerLine)));
			}
		}

		private Point GetByteColumnAndRow(int index)
		{
			return new Point(index % this._editor.BytesPerLine, index / this._editor.BytesPerLine);
		}

		private RectangleF GetBound(Point point)
		{
			return new RectangleF((float)(this._recHexValue.X + point.X * this._recHexValue.Width), (float)(this._recHexValue.Y + point.Y * this._recHexValue.Height), (float)this._recHexValue.Width, (float)this._recHexValue.Height);
		}

		private bool IsHex(char c) => c >= 'a' && c <= 'f' || c >= 'A' && c <= 'F' || char.IsDigit(c);
	}
}