<?php
namespace Teknisa\PebLibs\Controllers;

use Zeedhi\Framework\DataSource\ParameterBag;
use Zeedhi\Framework\DTO;
use Zeedhi\Framework\DTO\Response\Error;
use Zeedhi\Framework\DataSource\DataSet;

abstract class TeknisaCrud {

	protected $crudService;
	protected $dataSourceName;
	protected $dataSourceNameToSave  = false;
    /** @var ParameterBag */
    protected $parameterBag;
    /** @var string[] */
    protected $parameterBagColumns = array();
    protected $environment;

    public function __construct($crudService, ParameterBag $parameterBag) {
		$this->crudService = $crudService;
        $this->parameterBag = $parameterBag;
	}

	public function save(DTO\Request $request, DTO\Response $response) {
		try {
			$dataSourceName = $this->dataSourceNameToSave ? $this->dataSourceNameToSave : $this->dataSourceName;

			$rows = $this->crudService->getRowsToSave($request, $dataSourceName);
			
			$this->crudService->save($dataSourceName, $rows);
            $response->addDataSet(new DataSet("columnsToReturn", $this->crudService->getColumnsToReturn()));
		} catch (\Exception $e) {
			$response->setError(new Error($e->getMessage(), 500));
		}
	}

	public function find(DTO\Request\Filter $request, DTO\Response $response) {
        try {
        	if(isset($this->environment)){
        		$nrorg = $this->environment->getNrOrgTrab();
		        $utPerfilAcess = $this->environment->getIdUtlPerfilFilial();
		        $codPerfilAcess = $this->environment->getNrPerfil();
		        $codOperador = $this->environment->getCdOperador();
        	}else{
        		$utPerfilAcess = 'N';
        	}
        	
            $filterCriteria = $request->getFilterCriteria();
            $filterCriteria->setDataSourceName($this->dataSourceName);
            
            $filterCriteria = $this->crudService->getFilterCriteriaWithNrOrg($filterCriteria);
            $newFilterCriteria = $this->crudService->getPopulatedFilterCriteria($filterCriteria, $this->parameterBagColumns);
            $this->crudService->find($response, $newFilterCriteria);
            
            if($utPerfilAcess == 'S'){
	            $pefilAcessParameterBagColumns = ["CDOPERADOR", "NRORG", "PERFILACESSO"];
	            $conditions =  array();
	            $perfilAcessFilterCriteria = new FilterCriteria('filial_filioper_perfilacess', $conditions);
	            $perfilAcessFilterCriteria->setDataSourceName('filial_filioper_perfilacess');
	            $perfilAcessFilterCriteria->addCondition('PERFILACESSO', $codPerfilAcess);
	            $perfilAcessFilterCriteria->addCondition('CDOPERADOR', $codOperador);
	            $perfilAcessFilterCriteria->addCondition('NRORG', $nrorg);
	            $perfilAcessFilterCriteria = $this->crudService->getFilterCriteriaWithNrOrg($perfilAcessFilterCriteria);
	            $populatedFilterCriteria = $this->crudService->getPopulatedFilterCriteria($perfilAcessFilterCriteria, $pefilAcessParameterBagColumns);
	            $acessResponse = new DTO\Response;
	            $this->crudService->find($acessResponse, $populatedFilterCriteria);

	            
	            $perfilDataSets = $acessResponse->getDataSets();
	            $perfilDataSets = $perfilDataSets[0]? $perfilDataSets[0] : $perfilDataSets;
	            $perfilRows = $perfilDataSets->getRows();
	            $allowedFiliais = array();
	            forEach($perfilRows as $perfilRow){
		            $allowedFilial = array_filter($perfilRow, function($value, $field){
		            	return $field == 'CDFILIAL';
		            }, ARRAY_FILTER_USE_BOTH);
		           if($allowedFilial)
		        	array_push($allowedFiliais, $allowedFilial['CDFILIAL']);
	            }
	            
	            $newDatasets = array();
            	$dataSets = $response->getDataSets(); 
            	forEach($dataSets as $dataSet){
	            	$datasetName = $dataSet->getDataSourceName();
	            	$rows = $dataSet->getRows();
	            	if(isset($rows[0])){
	            		$row = $rows[0];
	            		$hasTomManipulate = $this->array_some(array_keys($row), function($rowKey){
		            		return $rowKey == 'CDFILIAL';
	            		});
	            		if($hasTomManipulate){
	            			$manipulatedDataset = array();
	            			forEach($rows as $row){
	            				if(in_array($row['CDFILIAL'], $allowedFiliais))
	            					array_push($manipulatedDataset, $row);
	            			}
	            		}else{
	            			$manipulatedDataset = $rows;
	            		}
            			$newDataSet = new DataSet($datasetName, $manipulatedDataset);
            			
        				$response->setDataSets(array($newDataSet));
	            	}
            	}
	        }
        } catch (\Exception $e) {
            $response->setError(new Error($e->getMessage(), 500));
        }
    }

	public function delete(DTO\Request $request, DTO\Response $response) {
		try {
			$request = $this->crudService->buildDataSetIfRow($request, $this->dataSourceName);
            $dataSet = $request->getDataSet();
            $dataSet->setDataSourceName($this->dataSourceName);
            $this->crudService->delete($response, $dataSet);
		} catch (\Exception $e) {
			$response->setError(new Error($e->getMessage(), 500));
		}
	}
	
	public function array_some(array $array, callable $fn) {
        foreach ($array as $value) {
            if($fn($value)) {
                return true;
            }
        }
        return false;
    }
}