<?php

namespace App\Libs\Localization;

use Illuminate\Auth\AuthManager;
use Illuminate\Config\Repository;
use Illuminate\Http\Request;
use Illuminate\Routing\Router;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Str;
use Language;
use Website;

class Localization
{
    /**
     * Config repository.
     *
     * @var \Illuminate\Config\Repository
     */
    protected $configRepository;

    /**
     * Illuminate router class.
     *
     * @var \Illuminate\Routing\Router
     */
    protected $router;

    /**
     * @var Request
     */
    protected $request;

    /**
     * @var AuthManager
     */
    protected $auth;

    protected $currentLocale = false;
    protected $defaultLocale = false;
    protected $supportedLanguages = null;
    protected $allLanguages = null;
    protected $website = null;

    public function __construct(
        Repository $configRepository,
        Router $router,
        AuthManager $auth,
        Request $request
    ) {
        $this->configRepository = $configRepository;
        $this->auth = $auth;
        $this->router = $router;
        $this->request = $request;

        $this->defaultLocale = $this->configRepository->get('app.locale');
        $supportedLocales = $this->getAllSupportedLocales();
        if (empty($supportedLocales[$this->defaultLocale])) {
            throw new UnsupportedLocaleException("Laravel's default locale is not in the languages database table.");
        }
    }

    public function getRoutePrefix()
    {
        $locale = $this->request->segment(1);

        if (empty($locale)) {
            return null;
        }
        $language = $this->getAllLanguages()->find($locale);

        if (!empty($language)) {
            return $locale;
        } else {
            return null;
        }
    }

    public function commandInit(Website $website)
    {
        if (empty($website)) {
            throw new UnsupportedWebsiteException("This website doesn't exist");
        }
        $this->website = $website;

        $this->website->load(array(
            "languages" => function ($query) {
                $query->orderBy("website_language.position", "asc");
            }
        ));
        $this->supportedLanguages = $website->languages;

        if (empty($this->supportedLanguages)) {
            throw new UnsupportedLocaleException("This website doesn't have languages set");
        }
    }

    public function backendWebsiteFilter()
    {
        $website = get_website_from_url();
        if (empty($website)) {
            throw new UnsupportedWebsiteException("This website doesn't exist");
        }
        $this->website = $website;
        $user = $this->auth->guard('admin')->user();
        $websites = $user->websites;

        $website = $websites->find($this->website->id);

        if (empty($website)) {
            throw new UnsupportedWebsiteException("This website is not set for the current user");
        }

        $this->website->load(array(
            "languages" => function ($query) {
                $query->orderBy("website_language.position", "asc");
            }
        ));
        $this->supportedLanguages = $website->languages;

        if (empty($this->supportedLanguages)) {
            throw new UnsupportedLocaleException("This website doesn't have languages set");
        }
    }

    public function frontendLanguageFilter()
    {
        $locale = $this->router->getCurrentRoute()->getPrefix();
        $user = Auth::guard('admin')->user();
        if (!empty($locale) && Str::startsWith($locale,'/')) {
            $locale = Str::replaceFirst('/', '', $locale);
        }

        $website = get_website_from_url();
        if (empty($website)) {
            $website = Website::find(1);
            //throw new UnsupportedWebsiteException("This website doesn't exist");
        }
        $this->website = $website;
        $website->load(array(
            "languages" => function ($query) use ($user) {
                $query->orderBy("website_language.position", "asc");

                if (!$user) {
                    $query->where("website_language.is_active", true);
                }
            }
        ));

        $this->supportedLanguages = $website->languages;

        $defaultLanguage = $website->getDefaultLanguage();

        if (empty($defaultLanguage)) {
            throw new UnsupportedLocaleException("This website doesn't have a default language set");
        }

        $this->defaultLocale = $defaultLanguage->id;

        if (!empty($locale)) {
            $this->currentLocale = $locale;
            $websiteLanguage = $this->supportedLanguages->find($locale);

            if (empty($websiteLanguage) || (empty($user) && !$websiteLanguage->pivot->is_active)) {
                abort(404);
            }
        } else {
            $this->currentLocale = $this->defaultLocale;
        }

        app()->setLocale($this->currentLocale);
    }

    public function getLocalizedURL($locale = null, $url = null)
    {
        if (is_null($locale)) {
            $locale = $this->getActiveLocale();
        }

        if (is_null($url)) {
            $url = $this->request->fullUrl();
        }

        $base_path = $this->request->getBaseUrl();
        $parsed_url = parse_url($url);
        if (!isset($parsed_url['path'])) {
            $parsed_url['path'] = "";
        }
        $parsed_url['path'] = str_replace($base_path, '', '/'.ltrim($parsed_url['path'], '/'));
        $path = $parsed_url['path'];

        $parsed_url['path'] = preg_replace('%^/?'.$this->currentLocale.'/%', '$1', $parsed_url['path']);

        if ($parsed_url['path'] == $path) {
            $parsed_url['path'] = preg_replace('%^/?'.$this->currentLocale.'$%', '$1', $parsed_url['path']);
        }

        $parsed_url['path'] = ltrim($parsed_url['path'], '/');

        if ($locale != $this->getDefaultLocale()) {
            $parsed_url['path'] = $locale.'/'.ltrim($parsed_url['path'], '/');
        }

        //  $parsed_url['path'] = ltrim(ltrim($base_path, '/') . '/' . $parsed_url['path'], '/');

        if (Str::startsWith($path, '/') === true) {
            $parsed_url['path'] = '/'.$parsed_url['path'];
        }

        $finalUrl = $this->unparseUrl($parsed_url);


        return url($finalUrl);
    }

    protected function unparseUrl($parsed_url)
    {
        if (empty($parsed_url)) {
            return "";
        }

        $url = "";
        //    $url .= isset($parsed_url['scheme']) ? $parsed_url['scheme'] . '://' : '';
        //    $url .= isset($parsed_url['host']) ? $parsed_url['host'] : '';
        //    $url .= isset($parsed_url['port']) ? ':' . $parsed_url['port'] : '';
        //    $user = isset($parsed_url['user']) ? $parsed_url['user'] : '';
        //    $pass = isset($parsed_url['pass']) ? ':' . $parsed_url['pass']  : '';
        //     $url .= $user . (($user || $pass) ? "$pass@" : '');

        if (!empty($url)) {
            $url .= isset($parsed_url['path']) ? '/'.ltrim($parsed_url['path'], '/') : '';
        } else {
            $url .= isset($parsed_url['path']) ? $parsed_url['path'] : '';
        }

        $url .= isset($parsed_url['query']) ? '?'.$parsed_url['query'] : '';
        $url .= isset($parsed_url['fragment']) ? '#'.$parsed_url['fragment'] : '';

        return $url;
    }

    public function setSupportedLanguages($languages)
    {
        $this->supportedLanguages = $languages;
    }

    public function getSupportedLanguages()
    {
        return $this->supportedLanguages;
    }

    public function getAllLanguages()
    {
        if (!empty($this->allLanguages)) {
            return $this->allLanguages;
        }

        $this->allLanguages = Language::all();

        return $this->allLanguages;
    }

    public function getSupportedLocales()
    {
        $supportedLanguages = $this->getSupportedLanguages();
        return $supportedLanguages->keyBy("id")->toArray();

    }

    public function getAllSupportedLocales()
    {
        $supportedLanguages = $this->getAllLanguages();
        return $supportedLanguages->keyBy("id")->toArray();

    }

    public function getActiveLanguage()
    {
        $language = $this->getAllSupportedLocales()[$this->getActiveLocale()];
        return $language;
    }

    public function getActiveLocale()
    {
        if ($this->currentLocale) {
            return $this->currentLocale;
        }
        return $this->defaultLocale;
    }

    public function setActiveLocale($locale)
    {
        $this->currentLocale = $locale;
        app()->setLocale($locale);
    }

    public function getDefaultLocale()
    {
        return $this->defaultLocale;
    }

    public function getWebsite()
    {
        return $this->website;
    }

}


