<?php

namespace Seka\Terminy;

use Livewire\Livewire;
use Illuminate\Support\ServiceProvider;
use Seka\Terminy\Modul\TerminyRolesPermissions;
use Seka\Terminy\Services\External\Calendar\CalendarService;
use Seka\Terminy\Composers\Udalosti\ZoznamBuducichUdalostiComposer;
use Seka\Terminy\Services\External\Calendar\Google\GoogleCalendarService;
use Seka\Terminy\Http\Controllers\Backend\Adresar\Livewire\Pages\Nove as AdresarNovePage;
use Seka\Terminy\Http\Controllers\Backend\Adresar\Livewire\Pages\Index as AdresarIndexPage;
use Seka\Terminy\Http\Controllers\Backend\Udalosti\Livewire\Pages\Nova as UdalostiNovaPage;
use Seka\Terminy\Http\Controllers\Backend\Udalosti\Livewire\Pages\Index as UdalostiIndexPage;
use Seka\Terminy\Http\Controllers\Livewire\Components\Udalosti\Stav as UdalostiStavComponent;
use Seka\Terminy\Http\Controllers\Livewire\Components\Udalosti\Druh as UdalostiDruhComponent;
use Seka\Terminy\Http\Controllers\Backend\Adresar\Livewire\Pages\Upravit as AdresarUpravitPage;
use Seka\Terminy\Http\Controllers\Backend\Udalosti\Livewire\Pages\Upravit as UdalostiUpravitPage;
use Seka\Terminy\Http\Controllers\Backend\Adresar\Livewire\Components\Form as AdresarFormComponent;
use Seka\Terminy\Http\Controllers\Backend\Udalosti\Livewire\Components\Form as UdalostiFormComponent;
use Seka\Terminy\Http\Controllers\Backend\Adresar\Livewire\Components\Zoznam as AdresarZoznamComponent;
use Seka\Terminy\Http\Controllers\Backend\Udalosti\Livewire\Components\Zoznam as UdalostiZoznamComponent;
use Seka\Terminy\Http\Controllers\Backend\Registracie\Livewire\Components\Form as RegistracieFormComponent;
use Seka\Terminy\Http\Controllers\Frontend\Registracie\Livewire\Components\Form as FrontendRegistracieFormComponent;

/**
 * Class TerminyServiceProvider
 *
 * @package Seka\Terminy
 */
final class TerminyServiceProvider extends ServiceProvider
{
    /**
     * @throws \Illuminate\Contracts\Container\BindingResolutionException
     */
    public function boot(): void
    {
        $this->app->bind(TerminyRolesPermissions::class, function () {
            return new TerminyRolesPermissions();
        });

        $this->app->bind(CalendarService::class, function () {
            return new GoogleCalendarService();
        });

        $this->app->tag([
            TerminyRolesPermissions::class,
        ], 'roleaopravnenia');

        $this->app->booted(function () {
            $this->breadcrumbs();
        });

        $this->loadViewsFrom(__DIR__.'/../resources/views', 'Terminy');
        $this->loadLivewireComponents();

        $this->publishMigrations();
        $this->publishSeeders();
        $this->publishAssets();
        $this->publishConfig();
    }

    /**
     * @throws \Illuminate\Contracts\Container\BindingResolutionException
     */
    public function register(): void
    {
        $this->registerRoutes();
        $this->registerEvents();
        $this->registerComposers();
    }

    /**
     * @return void
     */
    public function registerEvents(): void
    {
        $this->app->register(EventServiceProvider::class);
    }

    /**
     *
     */
    protected function breadcrumbs(): void
    {
        if (class_exists('Breadcrumbs')) {
            // BACKEND
            require __DIR__ . '/../routes/backend/breadcrumbs.php';

            // FRONTEND
            require __DIR__ . '/../routes/frontend/breadcrumbs.php';
        }
    }

    /**
     * Register the package routes.
     *
     * @return void
     */
    private function registerRoutes(): void
    {
        $this->app->register(RouteServiceProvider::class);
    }

    /**
     * @throws \Illuminate\Contracts\Container\BindingResolutionException
     */
    public function registerComposers(): void
    {
        view()->composer(
            ['Terminy::pages.udalosti.frontend.show'],
            ZoznamBuducichUdalostiComposer::class
        );
    }

    /**
     * @throws \Illuminate\Contracts\Container\BindingResolutionException
     */
    private function publishSeeders(): void
    {
        $this->publishes([
            __DIR__ . '/../database/seeds/TerminyPouzivatelRoleOpravneniaDatabaseSeeder.php.stub' => database_path('seeds/TerminyPouzivatelRoleOpravneniaDatabaseSeeder.php'),
        ], 'seeds');
    }

    /**
     * @throws \Illuminate\Contracts\Container\BindingResolutionException
     */
    private function publishMigrations(): void
    {
        if ($this->app->runningInConsole()) {
            if (!class_exists('CreateTerminyUdalostUdalostiTable')) {
                $this->publishes([
                    __DIR__ . '/../database/migrations/create_terminy_udalost_udalosti_table.php.stub' => database_path('migrations/2020_12_09_135800_create_terminy_udalost_udalosti_table.php'),
                ], 'migrations');
            }

            if (!class_exists('CreateTerminyUdalostRegistracieTable')) {
                $this->publishes([
                    __DIR__ . '/../database/migrations/create_terminy_udalost_registracie_table.php.stub' => database_path('migrations/2020_12_09_142000_create_terminy_udalost_registracie_table.php'),
                ], 'migrations');
            }

            if (!class_exists('CreateTerminyUdalostMiestaKonaniaTable')) {
                $this->publishes([
                    __DIR__ . '/../database/migrations/create_terminy_udalost_miesta_konania_table.php.stub' => database_path('migrations/2021_02_02_125500_create_terminy_udalost_miesta_konania_table.php'),
                ], 'migrations');
            }

            if (!class_exists('UpdateMiestoKonaniaTerminyUdalostUdalostiTable')) {
                $this->publishes([
                    __DIR__ . '/../database/migrations/update_miesto_konania_terminy_udalost_udalosti_table.php.stub' => database_path('migrations/2021_03_07_002500_update_miesto_konania_terminy_udalost_udalosti_table.php'),
                ], 'migrations');
            }
        }
    }

    /**
     * @throws \Illuminate\Contracts\Container\BindingResolutionException
     */
    private function publishAssets()
    {
        $this->publishes([
            __DIR__.'/../public/assets' => public_path('vendor/seka/terminy'),
        ], 'assets');
    }

    /**
     * Publish Config
     *
     * @return void
     * @throws \Illuminate\Contracts\Container\BindingResolutionException
     */
    public function publishConfig(): void
    {
        $configPathTerminy = __DIR__ . '/../config/terminy.php';
        $configPathGeocoder = __DIR__ . '/../config/geocoder.php';

        if ($this->app->runningInConsole()) {
            $this->publishes([
                $configPathTerminy => config_path('terminy.php'),
            ], 'config');
        }

        $this->mergeConfigFrom($configPathTerminy, "terminy");
        $this->mergeConfigFrom($configPathGeocoder, "geocoder");
    }

    /**
     *
     */
    private function loadLivewireComponents(): void
    {
        // PAGES
        Livewire::component('Terminy::pages.adresar.backend.livewire.nove', AdresarNovePage::class);
        Livewire::component('Terminy::pages.adresar.backend.livewire.index', AdresarIndexPage::class);
        Livewire::component('Terminy::pages.adresar.backend.livewire.upravit', AdresarUpravitPage::class);
        Livewire::component('Terminy::pages.udalosti.backend.livewire.nova', UdalostiNovaPage::class);
        Livewire::component('Terminy::pages.udalosti.backend.livewire.index', UdalostiIndexPage::class);
        Livewire::component('Terminy::pages.udalosti.backend.livewire.upravit', UdalostiUpravitPage::class);

        // COMPONENTS
        Livewire::component('Terminy::components.livewire.udalosti.druh', UdalostiDruhComponent::class);
        Livewire::component('Terminy::components.livewire.udalosti.stav', UdalostiStavComponent::class);
        Livewire::component('Terminy::pages.adresar.backend.livewire.components.form', AdresarFormComponent::class);
        Livewire::component('Terminy::pages.adresar.backend.livewire.components.zoznam', AdresarZoznamComponent::class);
        Livewire::component('Terminy::pages.udalosti.backend.livewire.components.form', UdalostiFormComponent::class);
        Livewire::component('Terminy::pages.udalosti.backend.livewire.components.zoznam', UdalostiZoznamComponent::class);
        Livewire::component('Terminy::pages.udalosti.registracie.backend.livewire.components.form', RegistracieFormComponent::class);
        Livewire::component('Terminy::pages.udalosti.registracie.frontend.livewire.components.form', FrontendRegistracieFormComponent::class);
    }
}
