<?php

namespace App\Libraries\API\HPILO;

use App\Entities\HPILOEntity;
use App\Libraries\Adapter\API\Adapter;

class HPILO4
{
    private $_adapter = null;
    private $_system = array();
    protected $_base_url = "/redfish/v1";
    public function __construct(Adapter $adapter)
    {
        $this->_adapter = $adapter;
    }
    private function getSystemInfo()
    {
        $results = $this->_adapter->get($this->_base_url . "/Systems/1/");
        $this->_system['model'] = sprintf("%s %s", $results->Model, $results->BiosVersion);
        $this->_system['processor'] = trim($results->Processors->ProcessorFamily) . " * " . $results->Processors->Count;
        $this->_system['memory'] = $results->Memory->TotalSystemMemoryGB;
        $this->_system['health'] = 'OK';
        $this->_system['power'] = $results->Power;
        $this->_system['detail'] = '';
    }

    private function getMemoryInfo($url)
    {
        //url에서 맨앞의 /를 없애야함(substr사용)
        $results = $this->_adapter->get($url);
        //오류체크
        if ($results->DIMMStatus != "GoodInUse") {
            $this->_system['health'] = "ERROR";
        }
        return sprintf(
            "%s: %s %sMhz %sMB => %s",
            $results->SocketLocator,
            $results->DIMMType,
            $results->MaximumFrequencyMHz,
            $results->SizeMB,
            $results->DIMMStatus
        );
    }
    private function getMemoryInfos(): array
    {
        $results = $this->_adapter->get($this->_base_url . "/Systems/1/Memory/");
        $memorys = array("\n------Memory------");
        foreach ($results->links->Member as $link) {
            array_push($memorys, $this->getMemoryInfo($link->href));
        }
        return $memorys;
    }

    private function getPhysicalDiskInfo($url)
    {
        //url에서 맨앞의 /를 없애야함(substr사용)
        $info = $this->_adapter->get($url);
        //오류체크
        if ($info->Status->Health != "OK") {
            $this->_system['health'] = "ERROR";
        }
        return sprintf(
            "%s %s %sGB => %s",
            $info->MediaType,
            $info->Model,
            $info->CapacityGB,
            $info->Status->Health
        );
    }
    private function getPhysicalDiskInfos(): array
    {
        $results = $this->_adapter->get($this->_base_url . "/Systems/1/SmartStorage/ArrayControllers/0/DiskDrives/");
        $disks = array("\n------Physical Disk------");
        if (isset($results->links->Member)) {
            foreach ($results->links->Member as $link) {
                array_push($disks, $this->getPhysicalDiskInfo($link->href));
            }
        }
        return $disks;
    }

    private function getLogicalDiskInfo($url)
    {
        //url에서 맨앞의 /를 없애야함(substr사용)
        $info = $this->_adapter->get($url);
        //오류체크
        if ($info->Status->Health != "OK") {
            $this->_system['health'] = "ERROR";
        }
        return sprintf(
            "%s Raid:%s %s_%s %sMB => %s",
            $info->LogicalDriveType,
            $info->Raid,
            $info->Name,
            $info->Id,
            number_format($info->CapacityMiB),
            $info->Status->Health
        );
    }
    private function getLogicalDiskInfos(): array
    {
        $results = $this->_adapter->get($this->_base_url . "/Systems/1/SmartStorage/ArrayControllers/0/LogicalDrives/");
        $disks = array("\n------Logical Disk------");
        if (isset($results->links->Member)) {
            foreach ($results->links->Member as $link) {
                array_push($disks, $this->getLogicalDiskInfo($link->href));
            }
        }
        return $disks;
    }

    private function getFanInfos(): array
    {
        $results = $this->_adapter->get($this->_base_url . "/Chassis/1/Thermal/");
        $fans = array("\n------Fan------");
        foreach ($results->Fans as $fan) {
            //오류체크
            if ($fan->Status->Health != "OK") {
                $this->_system['health'] = "ERROR";
            }
            array_push($fans, sprintf("%s => %s", $fan->FanName, $fan->Status->Health));
        }
        return $fans;
    }

    public function console()
    {
        // Oem / Hp / Privileges / RemoteConsolePriv
        $results = $this->_adapter->get($this->_base_url . "/Sessions/");
        return $results->Items[0]->Id;
        // return $this->_adapter->get($results->Oem->Hp->links->MySession->href);
    }

    public function reset(string $type)
    {
        //resetType : "On","ForceOff","ForceRestart","Nmi","PushPowerButton"
        switch ($type) {
            case 'On':
                $resetType = 'On';
                break;
            case 'Off':
                $resetType = 'ForceOff';
                break;
            case 'Restart':
                $resetType = 'ForceRestart';
                break;
            default:
                throw new \Exception(__FUNCTION__ . "에서 {$type}은 기능은 없습니다.");
                break;
        }
        return $this->_adapter->post($this->_base_url . "/Systems/1", array("Action" => 'Reset', "ResetType" => $resetType));
    }

    public function refresh(HPILOEntity $entity): HPILOEntity
    {
        $this->getSystemInfo();
        $this->_system['detail'] .= implode("\n", $this->getMemoryInfos());
        $this->_system['detail'] .= implode("\n", $this->getPhysicalDiskInfos());
        $this->_system['detail'] .= implode("\n", $this->getLogicalDiskInfos());
        $this->_system['detail'] .= implode("\n", $this->getFanInfos());
        foreach ($this->_system as $field => $value) {
            $entity->$field = $value;
        }
        return $entity;
    }
}
