using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace _5_MagicSquares {
	internal class Calculations {
		public static int[,] GenerateMatrix_Middle(int size) {
			var returned = new int[size, size];
			var middle = size / 2;

			var val = 1;
			var x = middle;
			var y = size - 1;

			while (true) {
				if (CheckFullness(returned))
					break;

				returned[x, y] = val++;

				var next = GetNextPos(size, (x, y), (1, 1));
				if (returned[next.x, next.y] != 0) {
					next = GetNextPos(size, (x, y), (0, -1));
				}

				x = next.x;
				y = next.y;
			}

			return returned;
		}

		public static bool CheckMatrix(int[,] matrix) {
			var val = GetRowTotal(matrix, 0);

			for (var y = 1; y < matrix.GetLength(1); y++)
				if (GetRowTotal(matrix, y) != val)
					return false;


			for (var x = 0; x < matrix.GetLength(0); x++)
				if (GetColTotal(matrix, x) != val)
					return false;

			var diag0 = 0;
			var diag1 = 0;
			for (var i = 0; i < matrix.GetLength(0); i++) {
				diag0 += matrix[i, i];
				diag1 += matrix[i, matrix.GetLength(0) - 1 - i];
			}

			if (diag0 != val || diag1 != val)
				return false;

			return true;
		}

		static int GetRowTotal(int[,] matrix, int row) {
			var ret = 0;

			for (var i = 0; i < matrix.GetLength(0); i++) {
				ret += matrix[i, row];
			}

			return ret;
		}

		static int GetColTotal(int[,] matrix, int col) {
			var ret = 0;

			for (var i = 0; i < matrix.GetLength(1); i++) {
				ret += matrix[col, i];
			}

			return ret;
		}

		private static (int x, int y) GetNextPos(int size, (int x, int y) curr, (int x, int y) step) {
			(int x, int y) returned = (curr.x + step.x, curr.y + step.y);

			while (returned.x >= size)
				returned.x -= size;
			while (returned.x < 0)
				returned.x += size;

			while (returned.y >= size)
				returned.y -= size;
			while (returned.y < 0)
				returned.y += size;

			return returned;
		}

		private static bool CheckFullness(int[,] matrix) {
			for (var y = 0; y < matrix.GetLength(1); y++) {
				for (var x = 0; x < matrix.GetLength(0); x++) {
					if (matrix[x, y] == 0)
						return false;
				}
			}

			return true;
		}
	}
}
