using System;
using System.Drawing;
using System.IO;
using OpenTK;
using OpenTK.Graphics.OpenGL;

namespace SharpQuake
{
	internal static class Scr
	{
		public static viddef_t vid
		{
			get
			{
				return Scr._VidDef;
			}
		}

		public static cvar ViewSize
		{
			get
			{
				return Scr._ViewSize;
			}
		}

		public static float ConCurrent
		{
			get
			{
				return Scr._ConCurrent;
			}
		}

		public static bool CopyEverithing
		{
			get
			{
				return Scr._CopyEverything;
			}
			set
			{
				Scr._CopyEverything = value;
			}
		}

		public static void Init()
		{
			if (Scr._ViewSize == null)
			{
				Scr._ViewSize = new cvar("viewsize", "100", true);
				Scr._Fov = new cvar("fov", "90");
				Scr._ConSpeed = new cvar("scr_conspeed", "3000");
				Scr._CenterTime = new cvar("scr_centertime", "2");
				Scr._ShowRam = new cvar("showram", "1");
				Scr._ShowTurtle = new cvar("showturtle", "0");
				Scr._ShowPause = new cvar("showpause", "1");
				Scr._PrintSpeed = new cvar("scr_printspeed", "8");
				Scr._glTripleBuffer = new cvar("gl_triplebuffer", "1", true);
			}
			cmd.Add("screenshot", new xcommand_t(Scr.ScreenShot_f));
			cmd.Add("sizeup", new xcommand_t(Scr.SizeUp_f));
			cmd.Add("sizedown", new xcommand_t(Scr.SizeDown_f));
			Scr._Ram = Drawer.PicFromWad("ram");
			Scr._Net = Drawer.PicFromWad("net");
			Scr._Turtle = Drawer.PicFromWad("turtle");
			if (common.HasParam("-fullsbar"))
			{
				Scr.FullSbarDraw = true;
			}
			Scr._IsInitialized = true;
		}

		public static void UpdateScreen()
		{
			if (Scr.BlockDrawing || !Scr._IsInitialized || Scr._InUpdate)
			{
				return;
			}
			Scr._InUpdate = true;
			try
			{
				if (mainwindow.Instance != null && mainwindow.Instance.VSync == VSyncMode.On != SharpQuake.vid.Wait)
				{
					mainwindow.Instance.VSync = (SharpQuake.vid.Wait ? VSyncMode.On : VSyncMode.Off);
				}
				Scr._VidDef.numpages = 2 + (int)Scr._glTripleBuffer.Value;
				Scr.CopyTop = false;
				Scr._CopyEverything = false;
				if (Scr.IsDisabledForLoading)
				{
					if (host.RealTime - Scr._DisabledTime <= 60.0)
					{
						return;
					}
					Scr.IsDisabledForLoading = false;
					Con.Print("Load failed.\n", Array.Empty<object>());
				}
				if (Con.IsInitialized)
				{
					Scr.BeginRendering();
					if (Scr._OldFov != Scr._Fov.Value)
					{
						Scr._OldFov = Scr._Fov.Value;
						Scr._VidDef.recalc_refdef = true;
					}
					if (Scr._OldScreenSize != Scr._ViewSize.Value)
					{
						Scr._OldScreenSize = Scr._ViewSize.Value;
						Scr._VidDef.recalc_refdef = true;
					}
					if (Scr._VidDef.recalc_refdef)
					{
						Scr.CalcRefdef();
					}
					Scr.SetUpToDrawConsole();
					view.RenderView();
					Scr.Set2D();
					Scr.TileClear();
					if (Scr._DrawDialog)
					{
						sbar.Draw();
						Drawer.FadeScreen();
						Scr.DrawNotifyString();
						Scr._CopyEverything = true;
					}
					else if (Scr._DrawLoading)
					{
						Scr.DrawLoading();
						sbar.Draw();
					}
					else if (client.cl.intermission == 1 && Key.Destination == keydest_t.key_game)
					{
						sbar.IntermissionOverlay();
					}
					else if (client.cl.intermission == 2 && Key.Destination == keydest_t.key_game)
					{
						sbar.FinaleOverlay();
						Scr.CheckDrawCenterString();
					}
					else
					{
						if (view.Crosshair > 0f)
						{
							Drawer.DrawCharacter(Scr._VRect.x + Scr._VRect.width / 2, Scr._VRect.y + Scr._VRect.height / 2, 43);
						}
						Scr.DrawRam();
						Scr.DrawNet();
						Scr.DrawTurtle();
						Scr.DrawPause();
						Scr.CheckDrawCenterString();
						sbar.Draw();
						Scr.DrawConsole();
						menu.Draw();
					}
					view.UpdatePalette();
					Scr.EndRendering();
				}
			}
			finally
			{
				Scr._InUpdate = false;
			}
		}

		public static void EndRendering()
		{
			mainwindow instance = mainwindow.Instance;
			if (instance == null)
			{
				return;
			}
			if (!Scr.SkipUpdate || Scr.BlockDrawing)
			{
				instance.SwapBuffers();
			}
			if (!SharpQuake.vid.WindowedMouse)
			{
				if (Scr._IsMouseWindowed)
				{
					input.DeactivateMouse();
					input.ShowMouse();
					Scr._IsMouseWindowed = false;
				}
			}
			else
			{
				Scr._IsMouseWindowed = true;
				if (Key.Destination == keydest_t.key_game && !input.IsMouseActive && client.cls.state != cactive_t.ca_disconnected)
				{
					input.ActivateMouse();
					input.HideMouse();
				}
				else if (input.IsMouseActive && Key.Destination != keydest_t.key_game)
				{
					input.DeactivateMouse();
					input.ShowMouse();
				}
			}
			if (Scr.FullSbarDraw)
			{
				sbar.Changed();
			}
		}

		public static void CenterPrint(string str)
		{
			Scr._CenterString = str;
			Scr.CenterTimeOff = Scr._CenterTime.Value;
			Scr._CenterTimeStart = (float)client.cl.time;
			Scr._CenterLines = 1;
			string centerString = Scr._CenterString;
			for (int i = 0; i < centerString.Length; i++)
			{
				if (centerString[i] == '\n')
				{
					Scr._CenterLines++;
				}
			}
		}

		public static void EndLoadingPlaque()
		{
			Scr.IsDisabledForLoading = false;
			Scr.FullUpdate = 0;
			Con.ClearNotify();
		}

		public static void BeginLoadingPlaque()
		{
			snd.StopAllSounds(true);
			if (client.cls.state != cactive_t.ca_connected)
			{
				return;
			}
			if (client.cls.signon != 4)
			{
				return;
			}
			Con.ClearNotify();
			Scr.CenterTimeOff = 0f;
			Scr._ConCurrent = 0f;
			Scr._DrawLoading = true;
			Scr.FullUpdate = 0;
			sbar.Changed();
			Scr.UpdateScreen();
			Scr._DrawLoading = false;
			Scr.IsDisabledForLoading = true;
			Scr._DisabledTime = host.RealTime;
			Scr.FullUpdate = 0;
		}

		public static bool ModalMessage(string text)
		{
			if (client.cls.state == cactive_t.ca_dedicated)
			{
				return true;
			}
			Scr._NotifyString = text;
			Scr.FullUpdate = 0;
			Scr._DrawDialog = true;
			Scr.UpdateScreen();
			Scr._DrawDialog = false;
			snd.ClearBuffer();
			do
			{
				Key.KeyCount = -1;
				sys.SendKeyEvents();
			}
			while (Key.LastPress != 121 && Key.LastPress != 110 && Key.LastPress != 27);
			Scr.FullUpdate = 0;
			Scr.UpdateScreen();
			return Key.LastPress == 121;
		}

		private static void SizeUp_f()
		{
			cvar.Set("viewsize", Scr._ViewSize.Value + 10f);
			Scr._VidDef.recalc_refdef = true;
		}

		private static void SizeDown_f()
		{
			cvar.Set("viewsize", Scr._ViewSize.Value - 10f);
			Scr._VidDef.recalc_refdef = true;
		}

		private static void ScreenShot_f()
		{
			string path = null;
			int i;
			for (i = 0; i <= 999; i++)
			{
				path = Path.Combine(common.GameDir, string.Format("quake{0:D3}.tga", i));
				if (sys.GetFileTime(path) == DateTime.MinValue)
				{
					break;
				}
			}
			if (i == 100)
			{
				Con.Print("SCR_ScreenShot_f: Couldn't create a file\n", Array.Empty<object>());
				return;
			}
			FileStream fileStream = sys.FileOpenWrite(path, true);
			if (fileStream == null)
			{
				Con.Print("SCR_ScreenShot_f: Couldn't create a file\n", Array.Empty<object>());
				return;
			}
			using (BinaryWriter binaryWriter = new BinaryWriter(fileStream))
			{
				binaryWriter.Write(0);
				binaryWriter.Write(2);
				binaryWriter.Write(0);
				binaryWriter.Write(0u);
				binaryWriter.Write(0u);
				binaryWriter.Write((byte)(Scr.glWidth & 255));
				binaryWriter.Write((byte)(Scr.glWidth >> 8));
				binaryWriter.Write((byte)(Scr.glHeight & 255));
				binaryWriter.Write((byte)(Scr.glHeight >> 8));
				binaryWriter.Write(24);
				binaryWriter.Write(0);
				byte[] array = new byte[Scr.glWidth * Scr.glHeight * 3];
				GL.ReadPixels<byte>(Scr.glX, Scr.glY, Scr.glWidth, Scr.glHeight, PixelFormat.Rgb, PixelType.UnsignedByte, array);
				int num = Scr.glWidth * Scr.glHeight * 3;
				for (i = 0; i < num; i += 3)
				{
					byte b = array[i];
					array[i] = array[i + 1];
					array[i + 1] = b;
				}
				binaryWriter.Write(array, 0, array.Length);
			}
			Con.Print("Wrote {0}\n", new object[]
			{
				Path.GetFileName(path)
			});
		}

		private static void BeginRendering()
		{
			Scr.glX = 0;
			Scr.glY = 0;
			Scr.glWidth = 0;
			Scr.glHeight = 0;
			INativeWindow instance = mainwindow.Instance;
			if (instance != null)
			{
				Size clientSize = instance.ClientSize;
				Scr.glWidth = clientSize.Width;
				Scr.glHeight = clientSize.Height;
			}
		}

		private static void CalcRefdef()
		{
			Scr.FullUpdate = 0;
			Scr._VidDef.recalc_refdef = false;
			sbar.Changed();
			if (Scr._ViewSize.Value < 30f)
			{
				cvar.Set("viewsize", "30");
			}
			if (Scr._ViewSize.Value > 120f)
			{
				cvar.Set("viewsize", "120");
			}
			if (Scr._Fov.Value < 10f)
			{
				cvar.Set("fov", "10");
			}
			if (Scr._Fov.Value > 170f)
			{
				cvar.Set("fov", "170");
			}
			float num;
			if (client.cl.intermission > 0)
			{
				num = 120f;
			}
			else
			{
				num = Scr._ViewSize.Value;
			}
			if (num >= 120f)
			{
				sbar.Lines = 0;
			}
			else if (num >= 110f)
			{
				sbar.Lines = 24;
			}
			else
			{
				sbar.Lines = 48;
			}
			bool flag = false;
			if ((double)Scr._ViewSize.Value >= 100.0)
			{
				flag = true;
				num = 100f;
			}
			else
			{
				num = Scr._ViewSize.Value;
			}
			if (client.cl.intermission > 0)
			{
				flag = true;
				num = 100f;
				sbar.Lines = 0;
			}
			num /= 100f;
			int num2 = Scr._VidDef.height - sbar.Lines;
			refdef_t refDef = render.RefDef;
			refDef.vrect.width = (int)((float)Scr._VidDef.width * num);
			if (refDef.vrect.width < 96)
			{
				num = 96f / (float)refDef.vrect.width;
				refDef.vrect.width = 96;
			}
			refDef.vrect.height = (int)((float)Scr._VidDef.height * num);
			if (refDef.vrect.height > Scr._VidDef.height - sbar.Lines)
			{
				refDef.vrect.height = Scr._VidDef.height - sbar.Lines;
			}
			if (refDef.vrect.height > Scr._VidDef.height)
			{
				refDef.vrect.height = Scr._VidDef.height;
			}
			refDef.vrect.x = (Scr._VidDef.width - refDef.vrect.width) / 2;
			if (flag)
			{
				refDef.vrect.y = 0;
			}
			else
			{
				refDef.vrect.y = (num2 - refDef.vrect.height) / 2;
			}
			refDef.fov_x = Scr._Fov.Value;
			refDef.fov_y = Scr.CalcFov(refDef.fov_x, (float)refDef.vrect.width, (float)refDef.vrect.height);
			Scr._VRect = refDef.vrect;
		}

		private static float CalcFov(float fov_x, float width, float height)
		{
			if (fov_x < 1f || fov_x > 179f)
			{
				sys.Error("Bad fov: {0}", new object[]
				{
					fov_x
				});
			}
			double num = (double)width / Math.Tan((double)fov_x / 360.0 * 3.1415926535897931);
			return (float)(Math.Atan((double)height / num) * 360.0 / 3.1415926535897931);
		}

		private static void SetUpToDrawConsole()
		{
			Con.CheckResize();
			if (Scr._DrawLoading)
			{
				return;
			}
			Con.ForcedUp = (client.cl.worldmodel == null || client.cls.signon != 4);
			if (Con.ForcedUp)
			{
				Scr._ConLines = (float)Scr._VidDef.height;
				Scr._ConCurrent = Scr._ConLines;
			}
			else if (Key.Destination == keydest_t.key_console)
			{
				Scr._ConLines = (float)(Scr._VidDef.height / 2);
			}
			else
			{
				Scr._ConLines = 0f;
			}
			if (Scr._ConLines < Scr._ConCurrent)
			{
				Scr._ConCurrent -= (float)((int)((double)Scr._ConSpeed.Value * host.FrameTime));
				if (Scr._ConLines > Scr._ConCurrent)
				{
					Scr._ConCurrent = Scr._ConLines;
				}
			}
			else if (Scr._ConLines > Scr._ConCurrent)
			{
				Scr._ConCurrent += (float)((int)((double)Scr._ConSpeed.Value * host.FrameTime));
				if (Scr._ConLines < Scr._ConCurrent)
				{
					Scr._ConCurrent = Scr._ConLines;
				}
			}
			if (Scr._ClearConsole++ < Scr._VidDef.numpages)
			{
				sbar.Changed();
				return;
			}
			if (Scr.ClearNotify++ >= Scr._VidDef.numpages)
			{
				Con.NotifyLines = 0;
			}
		}

		private static void TileClear()
		{
			refdef_t refDef = render.RefDef;
			if (refDef.vrect.x > 0)
			{
				Drawer.TileClear(0, 0, refDef.vrect.x, Scr._VidDef.height - sbar.Lines);
				Drawer.TileClear(refDef.vrect.x + refDef.vrect.width, 0, Scr._VidDef.width - refDef.vrect.x + refDef.vrect.width, Scr._VidDef.height - sbar.Lines);
			}
			if (refDef.vrect.y > 0)
			{
				Drawer.TileClear(refDef.vrect.x, 0, refDef.vrect.x + refDef.vrect.width, refDef.vrect.y);
				Drawer.TileClear(refDef.vrect.x, refDef.vrect.y + refDef.vrect.height, refDef.vrect.width, Scr._VidDef.height - sbar.Lines - (refDef.vrect.height + refDef.vrect.y));
			}
		}

		private static void DrawNotifyString()
		{
			int num = 0;
			int num2 = (int)((double)Scr.vid.height * 0.35);
			do
			{
				int num3 = Scr._NotifyString.IndexOf('\n', num);
				if (num3 == -1)
				{
					num3 = Scr._NotifyString.Length;
				}
				if (num3 - num > 40)
				{
					num3 = num + 40;
				}
				int num4 = num3 - num;
				if (num4 > 0)
				{
					int num5 = (Scr.vid.width - num4 * 8) / 2;
					int i = 0;
					while (i < num4)
					{
						Drawer.DrawCharacter(num5, num2, (int)Scr._NotifyString[num + i]);
						i++;
						num5 += 8;
					}
					num2 += 8;
				}
				num = num3 + 1;
			}
			while (num < Scr._NotifyString.Length);
		}

		private static void DrawLoading()
		{
			if (!Scr._DrawLoading)
			{
				return;
			}
			glpic_t glpic_t = Drawer.CachePic("gfx/loading.lmp");
			Drawer.DrawPic((Scr.vid.width - glpic_t.width) / 2, (Scr.vid.height - 48 - glpic_t.height) / 2, glpic_t);
		}

		private static void CheckDrawCenterString()
		{
			Scr.CopyTop = true;
			if (Scr._CenterLines > Scr._EraseLines)
			{
				Scr._EraseLines = Scr._CenterLines;
			}
			Scr.CenterTimeOff -= (float)host.FrameTime;
			if (Scr.CenterTimeOff <= 0f && client.cl.intermission == 0)
			{
				return;
			}
			if (Key.Destination != keydest_t.key_game)
			{
				return;
			}
			Scr.DrawCenterString();
		}

		private static void DrawRam()
		{
			if (Scr._ShowRam.Value == 0f)
			{
				return;
			}
			if (!render.CacheTrash)
			{
				return;
			}
			Drawer.DrawPic(Scr._VRect.x + 32, Scr._VRect.y, Scr._Ram);
		}

		private static void DrawTurtle()
		{
			if (Scr._ShowTurtle.Value == 0f)
			{
				return;
			}
			if (host.FrameTime < 0.1)
			{
				Scr._TurtleCount = 0;
				return;
			}
			Scr._TurtleCount++;
			if (Scr._TurtleCount < 3)
			{
				return;
			}
			Drawer.DrawPic(Scr._VRect.x, Scr._VRect.y, Scr._Turtle);
		}

		private static void DrawNet()
		{
			if (host.RealTime - (double)client.cl.last_received_message < 0.3)
			{
				return;
			}
			if (client.cls.demoplayback)
			{
				return;
			}
			Drawer.DrawPic(Scr._VRect.x + 64, Scr._VRect.y, Scr._Net);
		}

		private static void DrawPause()
		{
			if (Scr._ShowPause.Value == 0f)
			{
				return;
			}
			if (!client.cl.paused)
			{
				return;
			}
			glpic_t glpic_t = Drawer.CachePic("gfx/pause.lmp");
			Drawer.DrawPic((Scr.vid.width - glpic_t.width) / 2, (Scr.vid.height - 48 - glpic_t.height) / 2, glpic_t);
		}

		private static void DrawConsole()
		{
			if (Scr._ConCurrent > 0f)
			{
				Scr._CopyEverything = true;
				Con.Draw((int)Scr._ConCurrent, true);
				Scr._ClearConsole = 0;
				return;
			}
			if (Key.Destination == keydest_t.key_game || Key.Destination == keydest_t.key_message)
			{
				Con.DrawNotify();
			}
		}

		private static void DrawCenterString()
		{
			int num;
			if (client.cl.intermission > 0)
			{
				num = (int)((double)Scr._PrintSpeed.Value * (client.cl.time - (double)Scr._CenterTimeStart));
			}
			else
			{
				num = 9999;
			}
			int num2 = 48;
			if (Scr._CenterLines <= 4)
			{
				num2 = (int)((double)Scr._VidDef.height * 0.35);
			}
			string[] array = Scr._CenterString.Split(new char[]
			{
				'\n'
			});
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i].TrimEnd(new char[]
				{
					'\r'
				});
				int num3 = (Scr.vid.width - text.Length * 8) / 2;
				int j = 0;
				while (j < text.Length)
				{
					Drawer.DrawCharacter(num3, num2, (int)text[j]);
					if (num-- <= 0)
					{
						return;
					}
					j++;
					num3 += 8;
				}
				num2 += 8;
			}
		}

		private static void Set2D()
		{
			GL.Viewport(Scr.glX, Scr.glY, Scr.glWidth, Scr.glHeight);
			GL.MatrixMode(MatrixMode.Projection);
			GL.LoadIdentity();
			GL.Ortho(0.0, (double)Scr._VidDef.width, (double)Scr._VidDef.height, 0.0, -99999.0, 99999.0);
			GL.MatrixMode(MatrixMode.Modelview);
			GL.LoadIdentity();
			GL.Disable(EnableCap.DepthTest);
			GL.Disable(EnableCap.CullFace);
			GL.Disable(EnableCap.Blend);
			GL.Enable(EnableCap.AlphaTest);
			GL.Color4(1f, 1f, 1f, 1f);
		}

		public static bool IsDisabledForLoading;

		public static bool BlockDrawing = false;

		public static bool SkipUpdate;

		public static bool FullSbarDraw;

		public static bool IsPermedia;

		public static bool CopyTop;

		public static int ClearNotify;

		public static int glX;

		public static int glY;

		public static int glWidth;

		public static int glHeight;

		public static float CenterTimeOff;

		public static int FullUpdate;

		private static viddef_t _VidDef = new viddef_t();

		private static vrect_t _VRect;

		private static bool _DrawLoading;

		private static double _DisabledTime;

		private static bool _DrawDialog;

		private static bool _IsInitialized;

		private static bool _InUpdate;

		private static glpic_t _Ram;

		private static glpic_t _Net;

		private static glpic_t _Turtle;

		private static int _TurtleCount;

		private static bool _CopyEverything;

		private static float _ConCurrent;

		private static float _ConLines;

		private static int _ClearConsole;

		private static float _OldScreenSize;

		private static float _OldFov;

		private static int _CenterLines;

		private static int _EraseLines;

		private static float _CenterTimeStart;

		private static string _CenterString;

		private static cvar _ViewSize;

		private static cvar _Fov;

		private static cvar _ConSpeed;

		private static cvar _CenterTime;

		private static cvar _ShowRam;

		private static cvar _ShowTurtle;

		private static cvar _ShowPause;

		private static cvar _PrintSpeed;

		private static cvar _glTripleBuffer;

		private static string _NotifyString;

		private static bool _IsMouseWindowed;
	}
}
