package ru.dbotthepony.mc.otm.client.screen.panels;

import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
import ru.dbotthepony.mc.otm.client.screen.MatteryScreen;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

public class FlexGridPanel<S extends Screen> extends EditablePanel<S> {
	public enum FlexAlign {
		TOP_LEFT,
		TOP_CENTER,
		TOP_RIGHT,

		MIDDLE_LEFT,
		MIDDLE_CENTER,
		MIDDLE_RIGHT,

		BOTTOM_LEFT,
		BOTTOM_CENTER,
		BOTTOM_RIGHT
	}

	protected FlexAlign align = FlexAlign.MIDDLE_CENTER;
	public int panels_per_row = 1;

	public FlexGridPanel(@Nonnull S screen, @Nullable EditablePanel<?> parent, float x, float y, float width, float height) {
		super(screen, parent, x, y, width, height);
	}

	public FlexGridPanel(@Nonnull S screen, @Nullable EditablePanel<?> parent, float x, float y) {
		super(screen, parent, x, y);
	}

	public FlexGridPanel(@Nonnull S screen, @Nullable EditablePanel<?> parent) {
		super(screen, parent);
	}

	public FlexAlign getAlign() {
		return align;
	}

	public FlexGridPanel<S> setAlign(FlexAlign align) {
		this.align = align;
		return this;
	}

	@Override
	public void performLayout() {
		if (align == FlexAlign.MIDDLE_CENTER) {
			// список потомков
			var children = getUndockedVisibleChildren();

			if (children.size() == 0) {
				return;
			}

			// хранит общую ширину всех потомков в ряд
			// а так же ограничитель ширины ряда после
			// определения количества рядов
			float desired_width = 0;

			// минимально допустимая ширина одного ряда
			float min_width = getWidth();

			// "финальная" ширина этой панели
			float this_width = getWidth() - getDockPadding().getLeft() - getDockPadding().getRight();

			if (this_width <= 0) {
				return;
			}

			for (var child : children) {
				min_width = Math.min(min_width, child.getWidth() + child.getDockMargin().getLeft() + child.getDockMargin().getRight());
				desired_width += child.getWidth() + child.getDockMargin().getLeft() + child.getDockMargin().getRight();
			}

			int rows = 1;

			// если общая ширина больше чем ширина панели, делим пополам пока не найдем нужную ширину и количество рядов
			while (desired_width > this_width && desired_width > min_width) {
				desired_width /= 2;
				rows++;
			}

			if (desired_width < min_width) {
				desired_width = min_width;
			}

			int index;

			// определение высоты всех рядов вместе
			float total_height = 0;

			// утютю никаких goto
			// зато код чище некуда!
			while (desired_width <= this_width) {
				index = 0;
				total_height = 0;

				panels_per_row = 0;
				boolean calculate_row_width = true;

				for (int row = 0; row < rows; row++) {
					float max_height = 0;
					float total_width = 0;

					for (int i = index; i < children.size(); i++) {
						var child = children.get(i);
						var gain_width = child.getWidth() + child.getDockMargin().getLeft() + child.getDockMargin().getRight();

						index = i;

						if (gain_width + total_width > desired_width) {
							if (calculate_row_width) {
								panels_per_row = i + 1;
								calculate_row_width = false;
							}

							break;
						}

						max_height = Math.max(max_height, child.getHeight() + child.getDockMargin().getTop() + child.getDockMargin().getBottom());
						total_width += gain_width;
					}

					total_height += max_height;
				}

				if (index + 1 < children.size() && desired_width != this_width) {
					// не все панели уместились. ну чтож
					desired_width = Math.min(desired_width + min_width, this_width);
				} else {
					break;
				}
			}

			index = 0;

			// ширину на середину для позиционирования по центру
			this_width /= 2;

			// определение точки по середине по высоте
			float h_middle = (getHeight() - getDockPadding().getBottom() - getDockPadding().getTop() - total_height) / 2;

			// OverdriveThatMatters.LOGGER.info("Общая высота {}, рядов {}, середина {}", total_height, rows, h_middle);

			for (int row = 0; row < rows; row++) {
				float max_height = 0;
				float total_width = 0;

				int until = index;

				for (int i = index; i < children.size(); i++) {
					var child = children.get(i);
					var gain_width = child.getWidth() + child.getDockMargin().getLeft() + child.getDockMargin().getRight();

					until = i;

					if (gain_width + total_width > desired_width) {
						break;
					}

					max_height = Math.max(max_height, child.getHeight() + child.getDockMargin().getTop() + child.getDockMargin().getBottom());
					total_width += gain_width;
				}

				total_width /= 2;
				max_height /= 2;

				// OverdriveThatMatters.LOGGER.info("Ряд {}, общая ширина {}, максимальная высота {}, позиция {}, c {} до {}", row, total_width * 2, max_height * 2, h_middle, index, until);

				float accumulate_width = 0;

				for (int i = index; i <= until; i++) {
					var child = children.get(i);

					child.setPos((int) (this_width - total_width + accumulate_width + child.getDockMargin().getLeft()), (int) (h_middle + max_height - child.getHeight() / 2));
					accumulate_width += child.getWidth() + child.getDockMargin().getLeft() + child.getDockMargin().getRight();
				}

				h_middle += max_height * 2;

				index = until;
			}
		}

		super.performLayout();
	}
}
