<?php

namespace App\Presenters;

abstract class AbstractPresenter
{
    /**
     * The resource that is the object that was decorated.
     *
     * @var mixed
     */
    protected $entity;

    /**
     * @param $entity
     */
    public function __construct($entity)
    {
        $this->entity = $entity;
    }

    /**
     * Allow for property-style retrieval
     *
     * @param $property
     * @return mixed
     */
    public function __get($property)
    {
        if ($this->presentationMethodExists($property)) {
            $method = $this->getPresentationMethod($property);

            return $this->{$method}();
        }

        return $this->entity->{$property};
    }

    /**
     * Detect if property exists.
     *
     * @param $property
     * @return bool
     */
    public function __isset($property)
    {
        return $this->presentationMethodExists($property) || isset($this->entity->{$property});
    }

    /**
     * Allow for methods-style retrieval
     *
     * @param  string $name
     * @param  array  $arguments
     * @return mixed
     */
    public function __call($name, $arguments)
    {
        if ($this->presentationMethodExists($name)) {
            $method = $this->getPresentationMethod($name);

            return $this->{$method}(...$arguments);
        }

        return call_user_func_array([$this->entity, $name], $arguments);
    }

    /**
     * Determines presentation method exists.
     *
     * @param $property
     * @return bool
     */
    protected function presentationMethodExists($property)
    {
        return method_exists($this, $this->getPresentationMethod($property));
    }

    /**
     * Getter for name of presentation method for property.
     *
     * @param $property
     * @return string
     */
    protected function getPresentationMethod($property)
    {
        return 'present' . studly_case($property);
    }
}