<?php
namespace App\Traits;

use App\MaterialBox;
use App\Services\MaterialBoxService;
use App\Services\StationTaskCommodityService;

trait TestMockSubServices{
    /**
     * 例子：
     *  $this->service=$this->subMock([
     *   'class'=>StationTaskCommodityService::class,
     *   'subServices'=>[
     *  [
     *   'serviceName'=>'materialBoxService',
     *   'class'=>MaterialBoxService::class,
     *   'methods'=>[
     *   'firstOrCreate'=>new MaterialBox(['id'=>1]),
     *  ],
     *  ],
     *  ]
     * ]);
     * @param array $serviceDefinition
     * @return \PHPUnit\Framework\MockObject\MockObject
     */
    function subMock(array $serviceDefinition){
        $mockingService=$this->createPartialMock(
            $serviceDefinition['class'],
            isset($serviceDefinition['methods'])
                ?array_keys($serviceDefinition['methods']):[]
        );
        if(isset($serviceDefinition['methods']))
            foreach ($serviceDefinition['methods'] as $mName=>$mVal){
                $mockingService->method($mName)->willReturn($mVal);
            }
        if(isset($serviceDefinition['subServices']))
            $this->registerSubServices($mockingService,$serviceDefinition['subServices']);
        return $mockingService;
    }

    private function registerSubServices($rootService, $subServices){
        foreach ($subServices as $subService){
            $rootService->instant(
                $subService['serviceName'],
                ($subServiceMock=function()use($subService){
                    $subServiceMock=$this->createPartialMock(
                        $subService['class'],
                        array_keys($subService['methods'])
                    );
                    if(isset($subService['methods']))
                        foreach ($subService['methods'] as $methodName=>$methodVal){
                            $subServiceMock->method($methodName)->willReturn($methodVal);
                        }
                    if(isset($subService['subServices'])){
                        $this->registerSubServices($subServiceMock,$subService['subServices']);
                    }
                    return $subServiceMock;
                })()
            );
        }
    }

    function getTargetFieldCirculately($targetArr, $className='', $idName='id'){
        $amount = count($targetArr);

        $json_encode = json_encode($targetArr);
        $iName = 'i_' . md5($json_encode . $className);
        if(!isset($this->data[$iName])){
            $this->data[$iName]=$amount;
        }
        $this->data[$iName]++;
        if($this->data[$iName]>=$amount)
            $this->data[$iName]=0;
        return $targetArr[$this->data[$iName]][$idName];
    }
    function getIntegerIncreasely($markStr): int
    {
        $iName = 'i_' . $markStr;
        if(!isset($this->data[$iName])){
            $this->data[$iName]=-1;
        }
        $this->data[$iName]++;
        return $this->data[$iName];
    }
    function makeArray($amount,$array)
    {
        $resultArrays=[];
        for($i=0;$i<$amount;$i++){
            $newArr=[];
            foreach ($array as $key=>$item){
                if(gettype($item)=='object'){
                    $newArr[$key]=$item();
                }else{
                    $newArr[$key]=$item;
                }
            }
            $resultArrays[]= $newArr;
        }
        return $resultArrays;
    }
}
