<?php
    
    namespace frontend\components;
    
    use artbox\core\models\Alias;
    use artbox\core\services\Languages;
    use yii\helpers\Json;
    use yii\web\Request;
    
    /**
     * Url manager extended to work with aliases and languages
     *
     * @package artbox\core\seo
     */
    class UrlManager extends \yii\web\UrlManager
    {
        /**
         * @var bool
         */
        public $hideDefaultLanguagePrefix = false;
        
        /**
         * @see \yii\web\UrlManager
         * @var bool
         */
        public $enablePrettyUrl = true;
        
        /**
         * @see \yii\web\UrlManager
         * @var bool
         */
        public $showScriptName = false;
        
        /**
         * @var \artbox\core\services\Languages
         */
        protected $languages;
        
        /**
         * UrlManager constructor.
         *
         * @param \artbox\core\services\Languages $languages
         * @param array                           $config
         */
        public function __construct(Languages $languages, array $config = [])
        {
            $this->languages = $languages;
            
            parent::__construct($config);
        }
        
        /**
         * @param \yii\web\Request $request
         *
         * @return array|bool
         * @throws \artbox\core\exceptions\AliasOverwriteException
         * @throws \yii\base\InvalidConfigException
         */
        public function parseRequest($request)
        {
            //            $this->checkRedirect($request->url);
            
            $request = $this->parseLanguage($request);
            /**
             * @var Alias $alias
             */
            $alias = Alias::find()
                          ->where(
                              [
                                  'value' => trim($request->pathInfo, '/'),
                              ]
                          )
                          ->andWhere(
                              [
                                  'language_id' => $this->languages->getCurrent()->id,
                              ]
                          )
                          ->one();
            
            if ($alias !== null) {
                $params = Json::decode($alias->route);
                
                $route = array_shift($params);
                
                /**
                 * @todo REFACTOR AS SOO AS POSIBLE!
                 *       remove service locator, and implement Dependency Injection
                 * @var \artbox\core\components\SeoComponent $seo
                 */
                $seo = \Yii::$app->get('seo');
                $seo->setAlias($alias);
                return [
                    $route,
                    $params,
                ];
            }
            
            return parent::parseRequest($request);
        }
        
        /**
         * @param array|string $params
         *
         * @return string
         */
        public function createUrl($params)
        {
            if ($this->hideDefaultLanguagePrefix && ( $this->languages->getCurrent(
                    )->url == $this->languages->getDefault()->url )) {
                $prefix = '';
            } else {
                $prefix = '/' . $this->languages->getCurrent()->url;
            }
            
            if (isset($params[ 'alias' ])) {
                if ($params[ 'alias' ] instanceof Alias) {
                    return $prefix . '/' . $params[ 'alias' ]->value;
                } elseif (is_array($params[ 'alias' ])) {
                    return $prefix . '/' . $params[ 'alias' ][ 'value' ];
                }
            }
            
            return $prefix . parent::createUrl($params);
        }
        
        /**
         * @param $request
         *
         * @return mixed
         * @throws \yii\base\ExitException
         * @throws \yii\base\InvalidConfigException
         */
        protected function parseLanguage($request)
        {
            $split = explode('/', $request->pathInfo);
            if (in_array($split[ 0 ], array_keys($this->languages->getActive()))) {
                if ($this->hideDefaultLanguagePrefix && ( $split[ 0 ] == $this->languages->getDefault()->url )) {
                    
                    unset($split[ 0 ]);
                    
                    \Yii::$app->response->redirect('/' . implode('/', $split), 301)
                                        ->send();
                    \Yii::$app->end();
                } else {
                    $this->languages->setCurrent($split[ 0 ]);
                    
                    unset($split[ 0 ]);
                    
                    $request->setPathInfo(implode('/', $split));
                }
            } else {
                if ($this->hideDefaultLanguagePrefix) {
                    $this->languages->setCurrentDefault();
                } else {
                    \Yii::$app->response->redirect(
                        '/' . $this->languages->getDefault()->url . '/' . implode('/', $split),
                        301
                    )
                                        ->send();
                    \Yii::$app->end();
                }
            }
            
            return $request;
        }
        
        /**
         * Looks for rule in table(column) `redirect.from` if findes -
         * redirects to `redirect.to`
         *
         * @param string $url
         */
        protected function checkRedirect(string $url)
        {
            //            $redirect = Redirect::find()
            //                                ->where(
            //                                    [
            //                                        'from' => $url,
            //                                    ]
            //                                )
            //                                ->one();
            //
            //            if ($redirect) {
            //                \Yii::$app->response->redirect($redirect->to)
            //                                    ->send();
            //            }
        }
    }