<?php

namespace apexl\Io\includes;

use apexl\entityCore\Entity as BaseEntity;
use apexl\Io\operators\entityDatabaseOperator;
use apexl\Io\services\globalData;

class Entity extends BaseEntity{
    protected $table;
    protected $primaryKey;
    protected $performAccessChecks = TRUE;
    //the field in the database to perform access checks against
    protected $userAccessField = 'id';
    //the user field to perform the access check with
    protected $ownershipField = 'uid';

    protected $dataFields = [];

    protected $readOnlyFields = [];

    public function __construct($table, $primaryKey = 'id', $ownershipField = 'uid', $userAccessField = 'id')
    {
        $this->table = $table;
        $this->primaryKey = $primaryKey;
        $this->ownershipField = $ownershipField;
        $this->userAccessField = $userAccessField;
        parent::__construct();
        $this->setOperator(new entityDatabaseOperator($this->table, $this->primaryKey));
        $this->getEntityDataFields();
    }

    public function getEntityType()
    {
        return __CLASS__;
    }

    public function changeAccessCheckStatus($status){
        $this->performAccessChecks = $status;
    }

    public function setOwnershipField($field){
        $this->ownershipField = $field;
    }

    public function setUserAccessField($field){
        $this->userAccessField = $field;
    }

    /**
     * By default we want to store the current data object
     * @return $this
     * @throws \Exception
     */
    public function store(){
        parent::__call('store', [$this->data]);
        return $this;
    }

    public function delete($id = null){
        if($id){
            $this->{$this->primaryKey} = $id;
        }
        parent::__call('delete', [$this->{$this->primaryKey}]);
        //deleting? clear the data
        $this->data = [];
        return $this;
    }

    public function loadMultiple($conditions = [], $orderBy = [], $limit = FALSE, $offset = FALSE){
        $loaded = [];
        if(class_exists('\apexl\Io\modules\user\userModule') && $this->performAccessChecks){
            $user = (globalData::getInstance())->getData()['user'];
            $conditions = array_merge([$this->ownershipField => [$this->ownershipField, $user->{$this->userAccessField}]], $conditions);
        }
        $results = parent::__call('loadMultiple', [$conditions, $orderBy, $limit, $offset]);
        //build objects
        if(!empty($results)){
            foreach ($results as $result){
                $entityType = get_called_class();
                //set entity data (prevents us from having to reload entities)
                $entity = new $entityType();
                $entity->setData(System::makeUTF8Safe($result));
                //build an array of loaded entities
                $loaded[$entity->{$this->primaryKey}] = $entity;
            }
        }
        return $loaded;
    }

    /**
     * Function to get the fields for the entity (from the primary table).
     * Allows us to check what data is storable and strip data that isn't.
     * Will only return fields not specified as 'read only' in the entity settings.
     * @see the $readOnlyFields property.
     */
    public function getEntityDataFields(){
        if(empty($this->dataFields)) {
            $columns = $this->operator->getTableColumns();
            //build the data column.
            foreach($columns as $col){
                //is this a readonly field? if so, ignore it.
                if(!in_array($col->Field, $this->readOnlyFields)){
                    $this->dataFields[$col->Field] = $col;
                }
            }
        }
    }

    public function setReadOnlyFields(array $fields){
        $this->readOnlyFields = $fields;
    }

    public function totalEntities(){
        return parent::__call('totalEntities', []);
    }
}