<?php
/**
 * Created by PhpStorm.
 * User: radko
 * Date: 31.7.18
 * Time: 16:35
 */

namespace Seka\Vzdelavanie\Services;

use Illuminate\Support\Collection;
use Seka\Vzdelavanie\Repositories\Exceptions\ModelNotFoundException;
use Seka\Vzdelavanie\Repositories\Contracts\SekciaRepositoryInterface;
use Seka\Vzdelavanie\Repositories\Contracts\UcebnicaRepositoryInterface;
use Seka\Vzdelavanie\Repositories\Exceptions\ModelRelationshipsException;
use Illuminate\Database\Eloquent\ModelNotFoundException as EloquentModelNotFoundException;

/**
 * Class SekciaService
 * @package Seka\Vzdelavanie\Services
 */
class SekciaService extends Service implements SekciaServiceInterface
{
    /**
     * @var \Seka\Vzdelavanie\Repositories\Contracts\UcebnicaRepositoryInterface
     */
    protected $ucebnyTextRepository;

    /**
     * @var \Seka\Vzdelavanie\Repositories\Contracts\SekciaRepositoryInterface
     */
    protected $sekciaUcebnehoTextuRepository;

    /**
     * SekciaService constructor.
     * @param \Seka\Vzdelavanie\Repositories\Contracts\UcebnicaRepositoryInterface   $ucebnyTextRepository
     * @param \Seka\Vzdelavanie\Repositories\Contracts\SekciaRepositoryInterface     $sekciaUcebnehoTextuRepository
     */
    public function __construct(
        UcebnicaRepositoryInterface $ucebnyTextRepository,
        SekciaRepositoryInterface $sekciaUcebnehoTextuRepository
    )
    {
        $this->ucebnyTextRepository = $ucebnyTextRepository;
        $this->sekciaUcebnehoTextuRepository = $sekciaUcebnehoTextuRepository;
    }

    /**
     * @param int      $ucebnyTextId
     * @param array    $udaje
     * @param int|null $rodicSekcieId
     * @return mixed
     * @throws \Seka\Vzdelavanie\Repositories\Exceptions\ModelNotFoundException
     */
    public function vytvoritSekciuUcebnehoTextu(int $ucebnyTextId, array $udaje, int $rodicSekcieId = null)
    {
        /* @var \Seka\Vzdelavanie\Models\Kniznica\Ucebnica $ucebnyText */
        if ($ucebnyText = $this->ucebnyTextRepository->query()->find($ucebnyTextId)) {
            /* @var \Seka\Vzdelavanie\Models\Kniznica\Sekcia $sekcia */
            $udaje['ucebnica_id'] = $ucebnyText->getKey();

            if (!is_null($rodicSekcieId)) {
                $rodic = $this->sekciaUcebnehoTextuRepository->find($rodicSekcieId);

                return $rodic->children()->create($udaje);
            }

            return $this->sekciaUcebnehoTextuRepository->create($udaje);
        }

        throw new ModelNotFoundException('Učebný materiál neexistuje.');
    }

    /**
     * @param int   $sekciaId
     * @param array $data
     * @return mixed
     * @throws \Seka\Vzdelavanie\Repositories\Exceptions\ModelNotFoundException
     */
    public function upravit(int $sekciaId, array $data = [])
    {
        return $this->sekciaUcebnehoTextuRepository->update($data, $sekciaId);
    }

    /**
     * @param int $id
     *
     * @return mixed|\Seka\Vzdelavanie\Models\Kniznica\Sekcia
     * @throws \Seka\Vzdelavanie\Repositories\Exceptions\ModelNotFoundException
     */
    public function vratSekciu(int $id)
    {
        try {
            /* @var \Seka\Vzdelavanie\Models\Kniznica\Sekcia $sekcia */
            $sekcia = $this->sekciaUcebnehoTextuRepository
                ->query()
                ->with('ucebnica')
                ->with('oblubene')
                ->with('ancestors')
                ->with('descendants')
                ->find($id);

            $sekcia->children = $sekcia->children()->get()->each(function ($child) {
                $child->makeHidden(['obsah']);
            });

            return $sekcia;
        } catch (EloquentModelNotFoundException $e) {
            throw new ModelNotFoundException();
        }
    }

    /**
     * @param int  $id
     * @param bool $akoStrom
     * @param bool $request
     * @return \Illuminate\Support\Collection|\Kalnoy\Nestedset\Collection|mixed
     * @throws \Seka\Vzdelavanie\Repositories\Exceptions\ModelNotFoundException
     */
    public function vratZoznamSekciiUcebnehoTextu(int $id, bool $akoStrom = true, bool $request = false)
    {
        /* @var \Seka\Vzdelavanie\Models\Ucebnica $ucebnyText */
        if (!$ucebnyText = $this->ucebnyTextRepository->query()->find($id)) {
            throw new ModelNotFoundException('Učebný materiál neexistuje.');
        }

        if ($request) {
            /* @var \Kalnoy\Nestedset\Collection $zoznamSekcii */
            $zoznamSekciiQuery = $this->sekciaUcebnehoTextuRepository
                ->query()
                ->addSelect('_lft', '_rgt', 'ucebnica_id', 'parent_id')
                ->where('ucebnica_id', $ucebnyText->getKey())
                ->allowedFields('id', 'nazov', 'obsah')
                ->allowedIncludes('ucebnica', 'parent');
        } else {
            /* @var \Kalnoy\Nestedset\Collection $zoznamSekcii */
            $zoznamSekciiQuery = $this->sekciaUcebnehoTextuRepository
                ->query()
                ->addSelect('_lft', '_rgt', 'ucebnica_id', 'parent_id')
                ->with('oblubene', 'ucebnica.kategoria')
                ->where('ucebnica_id', $ucebnyText->getKey())
                ->exclude('obsah');
        }

        $zoznamSekcii = $zoznamSekciiQuery
            ->orderBy('_lft')
            ->get();

        if ($zoznamSekcii->isEmpty()) {
            return collect([]);
        }

        if ($akoStrom) {
            return $zoznamSekcii->toTree();
        }

        return $zoznamSekcii->toFlatTree();
    }

    /**
     * @param int $ucebnyTextId
     * @param int $sekciaId
     * @throws \Seka\Vzdelavanie\Repositories\Exceptions\ModelRelationshipsException
     * @throws \Seka\Vzdelavanie\Repositories\Exceptions\ModelNotFoundException
     */
    public function odstranSekciu(int $ucebnyTextId, int $sekciaId)
    {
        /* @var \Seka\Vzdelavanie\Models\Sekcia $sekcia */
        $sekcia = $this->sekciaUcebnehoTextuRepository->find($sekciaId);

        if ((int) $sekcia->ucebnica_id !== (int) $ucebnyTextId) {
            throw new ModelRelationshipsException('Sekcia nepatrí k učebnému materiálu.');
        }

        if ($sekcia->descendants->count()) {
            throw new ModelRelationshipsException('Na sekciu sa odkazujú iné vnorené sekcie.');
        }

        $this->sekciaUcebnehoTextuRepository->delete($sekciaId);
    }

    /**
     * @param string $text
     * @return \Illuminate\Support\Collection
     */
    public function vyhladaj(string $text): Collection
    {
        return $this->sekciaUcebnehoTextuRepository
            ->query()
            ->allowedIncludes('ucebnica.kategoria')
            ->where('nazov', 'like', sprintf('%%%s%%', $text))
            ->orWhere('obsah', 'like', sprintf('%%%s%%', $text))
            ->get();
    }
}
