<?php

namespace App\Http\Middleware;

use App\Album;
use App\Facade\Theme;
use App\Facade\UserConfig;
use App\Helpers\DbHelper;
use App\Label;
use Closure;
use Illuminate\Contracts\Encryption\DecryptException;
use Illuminate\Foundation\Application;
use Illuminate\Http\Request;
use Illuminate\Mail\Mailer;
use Illuminate\Support\Facades\View;

class GlobalConfiguration
{
    /**
     * The application instance.
     *
     * @var \Illuminate\Foundation\Application
     */
    protected $app;

    /**
     * Create a new middleware instance.
     *
     * @param  \Illuminate\Foundation\Application  $app
     * @return void
     */
    public function __construct(Application $app)
    {
        $this->app = $app;
    }

    public function handle(Request $request, Closure $next)
    {
        // We can always add the version number
        $this->addVersionNumberToView();

        // If running the installer, chances are our database isn't running yet
        if ($request->is('install/*'))
        {
            return $next($request);
        }

        // When running migrations, CLI tasks or the installer, don't need to add things to the view
        if (php_sapi_name() != 'cli')
        {
            $this->addThemeInfoToView();
            $this->addAlbumsToView();
            $this->addLabelsToView();
            $this->addFlashMessages();
        }

        // Set the default mail configuration as per user's requirements
        $this->updateMailConfig();

        return $next($request);
    }

    private function addAlbumsToView()
    {
        $albums = DbHelper::getAlbumsForCurrentUser_NonPaged()->get();
        View::share('g_albums', $albums);

        if (UserConfig::get('albums_menu_parents_only'))
        {
            // Only show top-level albums in the nav bar
            $navbarAlbums = $albums->filter(function($value, $key)
            {
                return is_null($value->parent_album_id);
            });
        }
        else
        {
            // If not just showing top-level albums, we can show all
            $navbarAlbums = $albums;
        }

        $navbarAlbumsToDisplay = UserConfig::get('albums_menu_number_items');
        View::share('g_albums_menu', $navbarAlbums->take($navbarAlbumsToDisplay));
        View::share('g_more_albums', $navbarAlbums->count() - $navbarAlbumsToDisplay);

        $albumsToUpload = DbHelper::getAlbumsForCurrentUser_NonPaged('upload-photos')->get();
        View::share('g_albums_upload', $albumsToUpload);
    }

    private function addFlashMessages()
    {
        /** @var Request $request */
        $request = app('request');
        if ($request->session()->has('error'))
        {
            View::share('error', $request->session()->get('error'));
        }

        if ($request->session()->has('success'))
        {
            View::share('success', $request->session()->get('success'));
        }
    }

    private function addLabelsToView()
    {
        $NUMBER_TO_SHOW_IN_NAVBAR = 5;
        $labelCount = Label::count();
        $labels = Label::all();
        $labelsToAdd = [];

        /** @var Label $label */
        foreach ($labels as $label)
        {
            $label->photos_count = $label->photoCount();
            $labelsToAdd[] = $label;
        }

        // Sort my photo count, then name
        usort($labelsToAdd, function(Label $a, Label $b)
        {
            if ($a->photos_count == $b->photos_count)
            {
                if ($a->name == $b->name)
                {
                    return 0;
                }
                else if ($a->name < $b->name)
                {
                    return -1;
                }
                else if ($a->name > $b->name)
                {
                    return 1;
                }
            }
            else if ($a->photos_count < $b->photos_count)
            {
                return -1;
            }
            else if ($a->photos_count > $b->photos_count)
            {
                return 1;
            }
        });
        $labelsToAdd = array_slice(array_reverse($labelsToAdd), 0, $NUMBER_TO_SHOW_IN_NAVBAR);

        View::share('g_labels', $labelsToAdd);
        View::share('g_more_labels', $labelCount - $NUMBER_TO_SHOW_IN_NAVBAR);
    }

    private function addThemeInfoToView()
    {
        $themeInfo = Theme::info();

        // Add each theme info element to the view - prefixing with theme_
        // e.g. $themeInfo['name'] becomes $theme_name in the view
        foreach ($themeInfo as $key => $value)
        {
            View::share('theme_' . $key, $value);
        }

        // Also add a theme_url key
        View::share('theme_url', sprintf('themes/%s', Theme::current()));
    }

    private function addVersionNumberToView()
    {
        $version = config('app.version');
        View::share('app_version', $version);
        View::share('app_version_url', $version);
    }

    private function updateMailConfig()
    {
        /** @var Mailer $mailer */
        $mailer = $this->app->mailer;
        $swiftMailer = $mailer->getSwiftMailer();

        /** @var \Swift_SmtpTransport $transport */
        $transport = $swiftMailer->getTransport();
        $transport->setHost(UserConfig::get('smtp_server'));
        $transport->setPort(intval(UserConfig::get('smtp_port')));

        $username = UserConfig::get('smtp_username');
        if (!is_null($username))
        {
            $transport->setUsername($username);
        }

        $password = UserConfig::get('smtp_password');
        if (!is_null($password))
        {
            try
            {
                $transport->setPassword(decrypt($password));
            }
            catch (DecryptException $ex)
            {
                // Unable to decrypt the password - presumably the app's key has changed
            }
        }

        if (UserConfig::get('smtp_encryption'))
        {
            $transport->setEncryption('tls');
        }

        $mailer->alwaysFrom(UserConfig::get('sender_address'), UserConfig::get('sender_name'));
    }
}