<?php

namespace App\Models\Product;

use Illuminate\Support\Collection;

use App\Interfaces\ProductSupplier;
use App\Models\Base\ProductType;
use App\Models\AdslSupplier;
use App\Models\AdslSupplierPlan;
use App\Traits\NextKey;

class Adsl extends ProductType implements ProductSupplier
{
	use NextKey;
	const RECORD_ID = 'adsl_plan';

	protected $table = 'ab_adsl_plan';

	public static $map = [
		'base_up_offpeak'=>'extra_up_offpeak',
		'base_down_offpeak'=>'extra_down_offpeak',
		'base_up_peak'=>'extra_up_peak',
		'base_down_peak'=>'extra_down_peak',
	];

	/**
	 * Map upstream metrics into traffic allowance metrics
	 *
	 * @var array
	 */
	public static $metrics = [
		'down_peak'=>'base_down_peak',
		'down_offpeak'=>'base_down_offpeak',
		'up_peak'=>'base_up_peak',
		'up_offpeak'=>'base_up_offpeak',
		'peer'=>'base_down_peak',
		'internal'=>'base_down_offpeak',
	];

	/**
	 * The suppliers product
	 *
	 * @return \Illuminate\Database\Eloquent\Relations\HasOne
	 */
	public function product()
	{
		return $this->hasOne(AdslSupplierPlan::class,'id','adsl_supplier_plan_id');
	}

	/**
	 * The supplier
	 *
	 * @return \Illuminate\Database\Eloquent\Relations\HasOneThrough
	 */
	public function supplier()
	{
		return $this->hasOneThrough(AdslSupplier::class,AdslSupplierPlan::class,'id','id','adsl_supplier_plan_id','supplier_id');
	}

	public function __get($key)
	{
		switch($key) {
			case 'speed':
				return $this->product->speed;
		}

		// If we dont have a specific key, we'll resolve it normally
		return parent::__get($key);
	}

	/** ATTRIBUTES **/

	/**
	 * Calculate the allowance array or traffic used array
	 *
	 * @param array Traffic Used in each metric.
	 * @param bool $ceil Round the numbers to integers
	 * @return array|string
	 */
	public function allowance(array $data=[],bool $ceil=TRUE): Collection
	{
		$config = collect();

		// Base Config
		foreach (array_keys(static::$map) as $k) {
			$config->put($k,$this->{$k});
		}

		// Excess Config
		foreach (array_values(static::$map) as $k) {
			$config->put($k,$this->{$k});
		}

		// Shaped or Charge
		$config->put('shaped',$this->extra_shaped);
		$config->put('charged',$this->extra_charged);

		// Metric - used to round down data in $data.
		$config->put('metric',$this->metric);

		return $this->product->allowance($config,$data,$ceil);
	}

	/**
	 * Return the suppliers cost for this service
	 *
	 * @return float
	 */
	public function allowance_cost(): float
	{
		$result = 0;
		foreach ($this->product->allowance(NULL,$this->allowance([])->toArray()) as $k=>$v) {
			$result += -$v*$this->product->{static::$map[$k]};
		}

		return $result;
	}

	/**
	 * Render the allowance as a string
	 * eg: 50/100
	 *
	 * @return string
	 */
	public function allowance_string(): string
	{
		$result = '';
		$data = $this->allowance();

		foreach ([
			'base_down_peak',
			'base_up_peak',
			'base_down_offpeak',
			'base_up_offpeak',
	         ] as $k)
		{
			if ($data->has($k)) {
				if ($result)
					$result .= '/';

				$result .= $data->get($k);
			}
		}

		return $result;
	}

	public function getCostAttribute(): float
	{
		// @todo Tax shouldnt be hard coded
		return ($this->product->base_cost+$this->allowance_cost())*1.1;
	}
}