<?php
require_once dirname(dirname(__DIR__)) . '/das/methods/vendor/autoload.php';

use MathPHP\Statistics\Regression;
use MathPHP\Statistics\Regression\ParametricRegression;
use MathPHP\Statistics\Regression\Methods;
use MathPHP\Statistics\Regression\Models;
use MathPHP\Exception;

class paramRegr extends ParametricRegression
{
    use Methods\LeastSquares;
    use Models\LinearModel;

    /**
     * Average of x
     * @var number
     */
    private $xbar;

    /**
     * Average of y
     * @var number
     */
    private $ybar;

    /**
     * Sum of squared deviations of x
     * @var number
     */
    private $SSx;

    /**
     * Sum of squares residuals
     * @var number
     */
    private $SSres;

    private $fit_constant;

    private $p;

    private $v;

    private $isInvertible;

    private $parameters;

    public function __construct($points, $degree)
    {
        $this->degree = $degree;

        parent::__construct($points);
    }

    /**
     * Calculates the regression parameters.
     *
     * @throws Exception\BadDataException
     * @throws Exception\IncorrectTypeException
     * @throws Exception\MatrixException
     * @throws Exception\MathException
     */
    public function calculate()
    {
        $this->fit_constant = 1;
        $this->p = $this->degree;
        $this->ν = $this->n - $this->p - $this->fit_constant;

        $X = $this->createDesignMatrix($this->xs);
        $Xt = $X->transpose(); // Xᵀ
        $isInvertible = $Xt->multiply($X)->isInvertible();
        $this->isInvertible = $isInvertible;

        if($isInvertible) $this->parameters = $this->leastSquares($this->ys, $this->xs, $this->degree)->getColumn(0);
    }

    public function getparameters()
    {
        return $this->parameters;
    }

    /**
     * Evaluate the regression equation at x
     * Uses the instance model's evaluateModel method.
     *
     * @param  float $x
     *
     * @return float
     */
    public function evaluate($x)
    {
        $value = 0;
        foreach($this->parameters as $key => $param)
        {
            $value += $param * pow($x, $key);
        }
        return $value;
    }
}
