<?php
require_once dirname(__DIR__) . '/base/spcchart.php';

/**
 * U
 */
class U extends spcChart
{
    public $decimals;

    public $dataframe;

    /**
     * SPC U chart σ method;
     *
     * @param string $col
     * @param string $type
     * @param bool $round
     * @access public
     * @return array
     */
    public function sigma($col, $groupNum, $type, $round = true)
    {
        $ubar = $this->uBar($col, $groupNum, $type, false);
        $σ    = sqrt($ubar / $groupNum);
        $σ    = $round ? round($σ, $this->decimals) : $σ;

        return $σ;
    }

    /**
     * SPC U chart group σ method;
     *
     * @param string $col
     * @param string $type
     * @param bool $round
     * @access public
     * @return array
     */
    public function groupSigma($points, $groupData, $round = true)
    {
        $groupSigma = array();
        $uGroupBar= $this->uGroupBar($points, $groupData, false);
        foreach($points as $key => $point)
        {
            $points[$key] === null ? $groupSigma[$key] = null : $groupSigma[$key] = sqrt($uGroupBar/$groupData[$key]);
            if($round) $groupSigma[$key] = round($groupSigma[$key], $this->decimals);
        }

        return $groupSigma;
    }


    /**
     * SPC U chart μ method;
     *
     * @param string $col
     * @param string $type
     * @param bool $round
     * @access public
     * @return array
     */
    public function uBar($col, $groupNum, $type, $round = true)
    {
        $data = $this->dataframe->col($col, $type);
        $ubar = $data->sum / ($groupNum * $data->numCount);

        return $round ? round($ubar, $this->decimals) : $ubar;
    }

    /**
     * SPC U chart μ method;
     *
     * @param string $col
     * @param string $type
     * @param bool $round
     * @access public
     * @return array
     */
    public function uGroupBar($points, $groupData, $round = true)
    {
        $uGroupBar = array_sum($points)/array_sum($groupData);
        return $round ? round($uGroupBar, $this->decimals) : $uGroupBar;
    }

    /**
     * If either of points and groupData is null, both are null.
     *
     * @param string $col
     * @param string $type
     * @param bool $round
     * @access public
     * @return array
     */
    public function setNull($points, $groupData)
    {
        $beforePoints = array();
        foreach($points as $key => $point)
        {
            if($points[$key] !== null and $groupData[$key] !== null)
            {
                $points[$key]       = $point/$groupData[$key];
                $beforePoints[$key] = $point;
            }
            else
            {
                $points[$key]       = null;
                $groupData[$key]    = null;
                $beforePoints[$key] = null;
            }
        }
        return array($points, $groupData, $beforePoints);
    }

    /**
     * C chart center line method.
     *
     * @param float $μ
     * @param float $σ
     * @param float $multiple
     * @access public
     * @return object
     */
    public function CL($μ, $σ, $multiple)
    {
        $result = new stdclass();

        $part  = (float)$multiple * $σ;

        $result->CL  = $μ;
        $result->UCL = $result->CL + $part;
        $result->LCL = $result->CL - $part;
        $result->LCL = max(0, $result->LCL);

        return $result;
    }

    /**
     * C chart limit line method.
     *
     * @param float $μ
     * @param float $σ
     * @param float $multiple
     * @param float $defaultMultiple
     * @access public
     * @return object
     */
    public function limit($μ, $σ, $multiple, $defaultMultiple = 3, $points = array())
    {
        $type = 'number';

        $multiples = $multiple;
        if(!in_array($defaultMultiple, $multiple)) $multiples[] = $defaultMultiple;

        $SLs = array();
        foreach($multiples as $m)
        {
            if(is_array($σ) and $points)
            {
                $UCL = array();
                $LCL = array();
                foreach($σ as $key => $value)
                {
                    $CLResult = $this->CL($μ, $value, $m);
                    $points[$key] === null ? $UCL[$key] = null : $UCL[$key] = $CLResult->UCL;
                    $points[$key] === null ? $LCL[$key] = null : $LCL[$key] = $CLResult->LCL;
                }
                $SLs[$m] = array($UCL, $LCL);
            }
            else
            {
                $CLResult = $this->CL($μ, $σ, $m);
                $SLs[$m] = array($CLResult->UCL, $CLResult->LCL);
            }
        }

        $result       = new stdclass();
        $result->CL   = $μ;
        $result->ULCL = $SLs[$defaultMultiple];
        $result->SLs  = $SLs;

        if(is_array($σ))
        {
            return $result;
        }
        else if($points and !is_array($σ))
        {
            $lineLength = count($points) - 1;
            foreach($result->SLs as $multi => $SLs)
            {
                $UCL = $result->SLs[$multi][0];
                $LCL = $result->SLs[$multi][1];
                $result->SLs[$multi][0] = array();
                $result->SLs[$multi][1] = array();

                foreach($points as $key => $point)
                {
                    $point === null ? $result->SLs[$multi][0][$key] = null : $result->SLs[$multi][0][$key] = $UCL;
                    $point === null ? $result->SLs[$multi][1][$key] = null : $result->SLs[$multi][1][$key] = $LCL;
                }
            }
        }

        return $result;
    }
}

