<?php

  class ShoppingCart {


    protected $products = null;
    protected $slots   = 0;


    public function __construct(DataStorage $products) {
      $this->products = $products;
    }


    public function setNumberOfSlots($slots) {
      if(is_null($slots) || false === is_int($slots) || $slots <= 0) {
        throw new DomainException(sprintf("Invalid product limit specified %s", (string)$slots));
      }
      $this->slots = $slots;
    }

    
    public function getRemainingSlots() {
      return $this->slots - $this->countProducts();
    }


    public function hasRemainingSlots() {
      return $this->getRemainingSlots() > 0;
    }


    public function add(Product $product, $quantity = 1) {
      if(isset($this->storage[$product->getId()])) {
        $this->products[$product->getId()]['quantity'] += $quantity;
      }
      else {
        if(false === $this->hasRemainingSlots()) {
          throw new DomainException("No more items can be added to the shopping cart");
        }
        $this->products[$product->getId()] = array(
          'product'  => $product,
          'quantity' => $quantity
        );
      }
    }


    public function remove(Product $product) {
      if(false === isset($this->products[$product->getId()])) {
        throw new DomainException(sprintf("Product with id %d is not in the shopping cart", $product->getId()));
      }

      unset($this->products[$product->getId()]);
    }


    public function removeAllProducts() {
      $this->products->removeAll();
    }

    public function countProducts() {
      return count($this->products);
    }


    public function getProductsAndQuantities() {
      return $this->products;
    }


    public function getTotal() {
      $sum = 0;
      foreach($this->products as $product) {
        $sum += $product['product']->getPrice() * $product['quantity'];
      }

      return $sum;
    }
  }