<?php

namespace AuthStack\UserDirectory\Model;

use function AuthStack\UserDirectory\routes;
use AuthStack\UserDirectory\Service\RESTService;
use Buckhill\Support\Traits\DotNotationAccessorTrait;

class Organization extends AbstractModel
{
    use DotNotationAccessorTrait;

    protected $service;

    public function getID(): int
    {
        return (int)$this->dotNotationFromArray($this->model, 'id');
    }

    /**
     * @return Organization
     */
    public function create(): Organization
    {
        return $this->__model($this->getService()->create($this->getModel()));
    }

    /**
     * @param int $id
     * @return Organization
     */
    public function createForAccount(int $id): Organization
    {
        return $this->__model($this->getService()->createForAccount($this->getModel(), $id));
    }

    /**
     * @param int $id
     * @return Organization
     */
    public function read(int $id): Organization
    {
        return $this->__model($this->getService()->read($id));
    }

    /**
     * @param array $data
     * @return bool
     */
    public function update(array $data): bool
    {
        $result = $this->getService()->update($this->getID(), $data);

        $this->model = array_merge($this->model, $data);

        return $result;
    }

    /**
     * @return bool
     */
    public function delete(): bool
    {
        return $this->getService()->delete($this->getID());
    }

    /**
     * @return bool
     */
    public function deactivate(): bool
    {
        return $this->getService()->deactivate($this->getID());
    }

    /**
     * @param int $id
     * @return array
     */
    public function children(int $id): array
    {
        return $this->getService()->children($id);
    }

    /**
     * @return array
     */
    public function getHierarchyIDs(): array
    {
        $hierarchy = [];

        // Add own ID
        $hierarchy[] = $this->getID();

        // Fetch the JSON data, decode, add to hierarchy
        $children = $this->getModel()['children'];

        if(!empty($children))
        {
            $children = json_decode($children, true);

            $hierarchy = array_merge($hierarchy, $children);
        }

        return $hierarchy;
    }

    /**
     * @param array $options
     * @return mixed
     */
    public function getMembers(array $options = []): array
    {
        return $this->getService()->members($this->getID(), $options);
    }

    /**
     * @param array $options
     * @return array
     */
    public function listing(array $options = []): array
    {
        return $this->getService()->listing($options);
    }

    /**
     * @return array
     */
    public function groups(): array
    {
        return $this->getService()->groups($this->getID());
    }

    /**
     * @param string $title
     * @return Organization
     */
    public function setTitle(string $title): self
    {
        $this->model['title'] = $title;

        return $this;
    }

    /**
     * @return string
     */
    public function getTitle(): string
    {
        return $this->dotNotationFromArray($this->model, 'title');
    }

    /**
     * @param string $description
     * @return Organization
     */
    public function setDescription(string $description): self
    {
        $this->model['description'] = $description;

        return $this;
    }

    /**
     * @return string
     */
    public function getDescription(): string
    {
        return $this->dotNotationFromArray($this->model, 'description', '');
    }

    /**
     * @return Organization
     */
    public function setActive(): self
    {
        $this->model['active'] = true;

        return $this;
    }

    public function getActive(): bool
    {
        return (bool)$this->dotNotationFromArray($this->model, 'active', false);
    }

    /**
     * @param int $id
     * @return Organization
     */
    public function setParentID(int $id): self
    {
        $this->model['parent_id'] = $id;

        return $this;
    }

    public function getParentID()
    {
        return $this->dotNotationFromArray($this->model, 'parent_id');
    }

    /**
     * @param array $data
     * @return Organization
     */
    public function setAdditional(array $data): self
    {
        $this->model['additional'] = $data;

        return $this;
    }

    /**
     * @param string $path
     * @param null $default
     * @return array|mixed|null
     */
    public function getAdditional(string $path, $default = null)
    {
        return $this->dotNotationFromArray($this->model, sprintf("additional.%s", $path), $default);
    }

    /**
     * @return \AuthStack\UserDirectory\Service\Organization
     */
    public function getService(): RESTService
    {
        if(!$this->service instanceof \AuthStack\UserDirectory\Service\Organization)
        {
            $baseUrl = $this->baseUrl;
            $authType = $this->auth_type;
            $token = $this->auth_token;

            $routes = routes($baseUrl, $authType, $token);

            $this->service = new \AuthStack\UserDirectory\Service\Organization($baseUrl, $routes['options'], $routes['routes']['organization']);

            if(!is_null($this->tz_offset) && !is_null($this->tz_dst))
            {
                $this->service->setTimeZoneOffset($this->tz_offset);
                $this->service->setTimeZoneDST($this->tz_dst);
            }
        }

        return $this->service;
    }

    /**
     * @param \AuthStack\UserDirectory\Service\Organization $service
     * @return $this
     */
    public function setService(RESTService $service)
    {
        $this->service = $service;

        return $this;
    }

    /**
     * @param Organization $model
     * @return Organization
     */
    protected function __model(Organization $model): Organization
    {
        $this->model = $model->getModel();

        return $model->setService($this->getService());
    }
}