<?php

namespace Repetito\Web;

// If this file is called directly, abort.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

use DVDoug\BoxPacker\VolumePacker;
use DVDoug\BoxPacker\ItemList;
use Repetito\Web\TestBox;
use Repetito\Web\TestItem;

class BoxPacker {

	/**
	 * Convert dimension to package unit based on WooCommerce dimension unit
	 *
	 * @param float $dimension The dimension value to convert
	 * @return float The dimension in package unit
	 */
	private static function convertToCmFromUnit( float $dimension, string $unit ): float {
		switch ( $unit ) {
			case 'm':
				return $dimension * 100; // meters to package unit
			case 'mm':
				return $dimension / 10; // millimeters to package unit
			case 'in':
				return $dimension * 2.54; // inches to package unit
			case 'yd':
				return $dimension * 91.44; // yards to package unit
			case 'cm':
			default:
				return $dimension; // already in package unit
		}
	}

	public static function fitsIntoPackage( array $cartItems, array $box, int $totalCartItems ): bool {
		$box = new TestBox(
			$box['name'],
			self::convertToCmFromUnit( $box['width'], $box['unit'] ),
			self::convertToCmFromUnit( $box['length'], $box['unit'] ),
			self::convertToCmFromUnit( $box['height'], $box['unit'] )
		);

		$items = new ItemList();
		$productDimensionUnit = get_option( 'woocommerce_dimension_unit' );

		foreach ( $cartItems as $cart_item => $values ) {
			$_product = wc_get_product( $values['data']->get_id() );
			$qty      = $values['quantity'];

			// Convert product dimensions to cm to match box dimensions
			$width  = self::convertToCmFromUnit( (float) $_product->get_width(), $productDimensionUnit );
			$length = self::convertToCmFromUnit( (float) $_product->get_length(), $productDimensionUnit );
			$height = self::convertToCmFromUnit( (float) $_product->get_height(), $productDimensionUnit );

			while ( $qty > 0 ) {
				$items->insert(
					new TestItem(
						'',
						(int) ceil($width),
						(int) ceil($length),
						(int) ceil($height)
					)
				);
				--$qty;
			}
		}

		$volumePacker = new VolumePacker( $box, $items );
		$packedBox    = $volumePacker->pack();

		// we wont fit even one item to the box
		if ( count( $packedBox->getItems() ) === 0 ) {
			return false;
		}

		// if we fit them all, we're fine
		return count( $packedBox->getItems() ) === $totalCartItems;
	}
}
